Bug 930808 - Upgrade to psutil 2.1.3 draft
authorGregory Szorc <gps@mozilla.com>
Tue, 23 Dec 2014 10:45:15 -0800
changeset 233883 90b02e514e5dd1249d97d83223ef8fcf20c9da94
parent 233882 e96572c694b2e780ed143a08b3c6670273a39fdb
child 505008 e22e480fcb076fc0485129297f42ff588c432459
push id307
push usergszorc@mozilla.com
push dateTue, 23 Dec 2014 19:11:38 +0000
bugs930808
milestone37.0a1
Bug 930808 - Upgrade to psutil 2.1.3 psutil 2.1.3 is replacing psutil 1.0.1. There are numerous bug fixes and feature enhancements in psutil worth obtaining. Source code was obtained from https://pypi.python.org/packages/source/p/psutil/psutil-2.1.3.tar.gz and uncompressed into python/psutil without modification except for the removal of the egg-info directory.
python/psutil/CREDITS
python/psutil/HISTORY
python/psutil/HISTORY.rst
python/psutil/INSTALL.rst
python/psutil/MANIFEST.in
python/psutil/Makefile
python/psutil/PKG-INFO
python/psutil/README
python/psutil/README.rst
python/psutil/TODO
python/psutil/docs/Makefile
python/psutil/docs/README
python/psutil/docs/_static/copybutton.js
python/psutil/docs/_static/favicon.ico
python/psutil/docs/_static/logo.png
python/psutil/docs/_static/sidebar.js
python/psutil/docs/_template/globaltoc.html
python/psutil/docs/_template/indexcontent.html
python/psutil/docs/_template/indexsidebar.html
python/psutil/docs/_template/page.html
python/psutil/docs/_themes/pydoctheme/static/pydoctheme.css
python/psutil/docs/_themes/pydoctheme/theme.conf
python/psutil/docs/conf.py
python/psutil/docs/index.rst
python/psutil/docs/make.bat
python/psutil/examples/disk_usage.py
python/psutil/examples/free.py
python/psutil/examples/iotop.py
python/psutil/examples/killall.py
python/psutil/examples/meminfo.py
python/psutil/examples/netstat.py
python/psutil/examples/nettop.py
python/psutil/examples/pmap.py
python/psutil/examples/process_detail.py
python/psutil/examples/ps.py
python/psutil/examples/top.py
python/psutil/examples/who.py
python/psutil/make.bat
python/psutil/psutil/__init__.py
python/psutil/psutil/_common.py
python/psutil/psutil/_compat.py
python/psutil/psutil/_error.py
python/psutil/psutil/_psbsd.py
python/psutil/psutil/_pslinux.py
python/psutil/psutil/_psmswindows.py
python/psutil/psutil/_psosx.py
python/psutil/psutil/_psposix.py
python/psutil/psutil/_pssunos.py
python/psutil/psutil/_psutil_bsd.c
python/psutil/psutil/_psutil_bsd.h
python/psutil/psutil/_psutil_common.c
python/psutil/psutil/_psutil_common.h
python/psutil/psutil/_psutil_linux.c
python/psutil/psutil/_psutil_linux.h
python/psutil/psutil/_psutil_mswindows.c
python/psutil/psutil/_psutil_mswindows.h
python/psutil/psutil/_psutil_osx.c
python/psutil/psutil/_psutil_osx.h
python/psutil/psutil/_psutil_posix.c
python/psutil/psutil/_psutil_posix.h
python/psutil/psutil/_psutil_sunos.c
python/psutil/psutil/_psutil_sunos.h
python/psutil/psutil/_psutil_windows.c
python/psutil/psutil/_psutil_windows.h
python/psutil/psutil/_pswindows.py
python/psutil/psutil/arch/bsd/process_info.c
python/psutil/psutil/arch/bsd/process_info.h
python/psutil/psutil/arch/mswindows/ntextapi.h
python/psutil/psutil/arch/mswindows/process_handles.c
python/psutil/psutil/arch/mswindows/process_handles.h
python/psutil/psutil/arch/mswindows/process_info.c
python/psutil/psutil/arch/mswindows/process_info.h
python/psutil/psutil/arch/mswindows/security.c
python/psutil/psutil/arch/mswindows/security.h
python/psutil/psutil/arch/osx/process_info.c
python/psutil/psutil/arch/osx/process_info.h
python/psutil/psutil/arch/windows/glpi.h
python/psutil/psutil/arch/windows/ntextapi.h
python/psutil/psutil/arch/windows/process_handles.c
python/psutil/psutil/arch/windows/process_handles.h
python/psutil/psutil/arch/windows/process_info.c
python/psutil/psutil/arch/windows/process_info.h
python/psutil/psutil/arch/windows/security.c
python/psutil/psutil/arch/windows/security.h
python/psutil/psutil/error.py
python/psutil/setup.py
python/psutil/test/README
python/psutil/test/_bsd.py
python/psutil/test/_linux.py
python/psutil/test/_osx.py
python/psutil/test/_posix.py
python/psutil/test/_sunos.py
python/psutil/test/_windows.py
python/psutil/test/test_memory_leaks.py
python/psutil/test/test_psutil.py
python/psutil/tox.ini
--- a/python/psutil/CREDITS
+++ b/python/psutil/CREDITS
@@ -1,60 +1,65 @@
 Intro
 =====
 
-We would like to recognize some of the people who have been instrumental in the
+I would like to recognize some of the people who have been instrumental in the
 development of psutil.
-I'm sure we are forgetting some people (feel free to email us), but here is a
+I'm sure I'm forgetting some people (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), web-address (W), country (C), description (D), (I) issues
-(issue tracker is at http://code.google.com/p/psutil/issues/list).
+(issue tracker is at https://github.com/giampaolo/psutil/issues).
 Really thanks to all of you.
 
+- Giampaolo
+
 Author
 ======
 
 N: Giampaolo Rodola'
 C: Italy
 E: g.rodola@gmail.com
-W: http://www.linkedin.com/in/grodola
+W: http://grodola.blogspot.com/
 
 Contributors
 ============
 
 N: Jay Loden
 C: NJ, USA
 E: jloden@gmail.com
-D: original co-author, initial design/bootstrap and continuing bug fixes
+D: original co-author, initial design/bootstrap and occasional bug fixes
 W: http://www.jayloden.com
 
 N: Jeremy Whitlock
 E: jcscoobyrs@gmail.com
+D: great help with OSX C development.
 I: 125, 150, 174, 206
 
 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
+D: help on Windows development (initial version of Process.username())
 
 N: Justin Venus
 E: justin.venus@gmail.com
 D: Solaris support
 I: 18
 
 N: Dave Daeschler
 C: USA
 E: david.daeschler@gmail.com
-D: initial design/bootstrap and continuing bug fixes
+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: Jeffery Kline
 E: jeffery.kline@gmail.com
@@ -175,8 +180,84 @@ 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: Jeff Tang
+W: https://github.com/mrjefftang
+I: 340, 529
+
+N: Yaolong Huang
+E: airekans@gmail.com
+W: http://airekans.github.io/
+I: 530
deleted file mode 100644
--- a/python/psutil/HISTORY
+++ /dev/null
@@ -1,574 +0,0 @@
-Bug tracker at http://code.google.com/p/psutil/issues
-
-
-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
-------------------
-
-NEW FEATURES
-
- * #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: extensively use unittest2 module in unit tests and provide
-         workarounds if this is not installed on python < 2.7.
-
-BUG FIXES
-
- * #374: [Windows] negative memory usage reported when processes use a lot of
-         memory.
- * #379: [Linux] Process.get_memory_maps() may raise ValueError.
- * #394: [OSX] 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
-------------------
-
-NEW FEATURES
-
- * #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: [OSX] 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: [OSX] 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: [OSX] Leak of Mach ports on OS X (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: [OSX] get_users() returns an empty list on OSX 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
-------------------
-
-NEW FEATURES
-
- * #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
-------------------
-
-NEW FEATURES
-
- * #216: [POSIX] get_connections() UNIX sockets support.
- * #220: [FreeBSD] get_connections() has been rewritten in C and no longer
-         requires lsof.
- * #222: [OSX] add support for process cwd.
- * #261: process extended memory info.
- * #295: [OSX] process executable path is now determined by asking the OS
-         instead of being guessed from process cmdline.
- * #297: [OSX] 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, OSX)
-          - wired (OSX, 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.
-
-BUGFIXES
-
- * #298: [OSX 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
-------------------
-
-NEW FEATURES
-
- * #293: [Windows] process executable path is now determined by asking the OS
-         instead of being guessed from process cmdline.
-
-BUGFIXES
-
- * #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
-------------------
-
-NEW FEATURES
-
- * #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, OSX 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.
-
-BUGFIXES
-
- * #193: psutil.Popen constructor can throw an exception if the spawned process
-         terminates quickly.
- * #240: [OSX] 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: [OSX] 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
-------------------
-
-BUGFIXES
-
- * #228: some example scripts were not working with python 3.
- * #230: [Windows / OSX] 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
-------------------
-
-NEW FEATURES
-
- * #150: network I/O counters. (OSX 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. (OSX 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.
-
-BUGFIXES
-
- * #135: [OSX] 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
-------------------
-
-NEW FEATURES
-
- * #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
-
-BUGFIXES
-
- * #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: OSX - 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
-------------------
-
-NEW FEATURES
-
- * #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: [OSX] get_process_open_files() implementation has been rewritten
-         in C and no longer relies on lsof resulting in a 3x speedup.
- * #153: [OSX] get_process_connection() implementation has been rewritten
-         in C and no longer relies on lsof resulting in a 3x speedup.
-
-BUGFIXES
-
- * #83:  process cmdline is empty on OSX 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
-------------------
-
-NEW FEATURES
-
- * #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.
-
-BUGFIXES
-
- * #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 OS X.
- * #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
-------------------
-
-NEW FEATURES
-
- * #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
-
-BUGFIXES
-
- * #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 OS X includes shared library size
- * #77: NoSuchProcess wasn't raised on Process.create_time if kill() was
-        used first.
-
-
-0.1.2 - 2009-05-06
-------------------
-
-NEW FEATURES
-
- * #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
-
-BUGFIXES
-
- * #36: [Windows] NoSuchProcess not raised when accessing timing methods.
- * #40: test_get_cpu_times() failing on FreeBSD and OS X.
- * #42: [Windows] get_memory_percent() raises AccessDenied.
-
-
-0.1.1 - 2009-03-06
-------------------
-
-NEW FEATURES
-
- * #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).
-
-BUGFIXES
-
- * #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 instances of PID 0 on OS
-        X and FreeBSD platforms.
-
-
-0.1.0 - 2009-01-27
-------------------
-
- * Initial release.
new file mode 100644
--- /dev/null
+++ b/python/psutil/HISTORY.rst
@@ -0,0 +1,885 @@
+Bug tracker at https://github.com/giampaolo/psutil/issues
+
+2.1.3 2014-09-26
+================
+
+**Bug fixes**
+
+- #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: [OSX] 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: [OSX] 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: [OSX] 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: [OSX] Leak of Mach ports on OS X (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: [OSX] get_users() returns an empty list on OSX 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: [OSX] add support for process cwd.
+- #261: process extended memory info.
+- #295: [OSX] process executable path is now determined by asking the OS
+  instead of being guessed from process cmdline.
+- #297: [OSX] 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, OSX)
+  - wired (OSX, 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.
+
+**Bugfixes**
+
+- #298: [OSX 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.
+
+**Bugfixes**
+
+- #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, OSX 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.
+
+**Bugfixes**
+
+- #193: psutil.Popen constructor can throw an exception if the spawned process
+  terminates quickly.
+- #240: [OSX] 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: [OSX] 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
+==================
+
+**Bugfixes**
+
+- #228: some example scripts were not working with python 3.
+- #230: [Windows / OSX] 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. (OSX 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. (OSX 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.
+
+**Bugfixes**
+
+- #135: [OSX] 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
+
+**Bugfixes**
+
+- #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: OSX - 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: [OSX] get_process_open_files() implementation has been rewritten
+  in C and no longer relies on lsof resulting in a 3x speedup.
+- #153: [OSX] get_process_connection() implementation has been rewritten
+  in C and no longer relies on lsof resulting in a 3x speedup.
+
+**Bugfixes**
+
+- #83:  process cmdline is empty on OSX 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.
+
+**Bugfixes**
+
+- #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 OS X.
+- #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
+
+**Bugfixes**
+
+- #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 OS X 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
+
+**Bugfixes**
+
+- #36: [Windows] NoSuchProcess not raised when accessing timing methods.
+- #40: test_get_cpu_times() failing on FreeBSD and OS X.
+- #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).
+
+**Bugfixes**
+
+- #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 instances of PID 0 on OSX and
+  FreeBSD platforms.
+
+
+0.1.0 - 2009-01-27
+==================
+
+- Initial release.
new file mode 100644
--- /dev/null
+++ b/python/psutil/INSTALL.rst
@@ -0,0 +1,144 @@
+============================
+Installing using pip on UNIX
+============================
+
+The easiest way to install psutil on UNIX is by using pip (but first you might
+need to install python header files; see later).
+First install pip:
+
+    $ wget https://bitbucket.org/pypa/setuptools/raw/bootstrap/ez_setup.py
+    python ez_setup.py
+
+...then run:
+
+    $ pip install psutil
+
+You may need to install gcc and python header files first (see later).
+
+
+=====================
+Installing on Windows
+=====================
+
+Just get the right installer for your Python version and architecture from:
+https://pypi.python.org/pypi/psutil/#downloads
+
+
+==================================
+Compiling on Windows using mingw32
+==================================
+
+First install mingw (http://www.mingw.org/) then add mingw "bin" folder to
+environment PATH (NOTE: this assumes MinGW is installed in C:\MinGW):
+
+    SET PATH=C:\MinGW\bin;%PATH%
+
+You can then compile psutil by running:
+
+    setup.py build -c mingw32
+
+To compile and install:
+
+    setup.py build -c mingw32 install
+
+You can also use make.bat which automatically sets the env variable for you:
+
+    make.bat build
+
+FWIW I managed to compile psutil against all 32-bit Python versions but not
+64 bit.
+
+
+========================================
+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
+
+...then run:
+
+    setup.py build
+
+...or:
+
+    make.bat build
+
+Compiling 64 bit versions of Python 2.6 and 2.7 with VS 2008 requires
+Windows SDK and .NET Framework 3.5 SP1 to be installed first.
+Once you have those run vcvars64.bat, then compile:
+http://stackoverflow.com/questions/11072521/
+
+If you do not have the right version of Visual Studio available then try using
+MinGW instead.
+
+
+===================
+Installing on Linux
+===================
+
+gcc is required and so the python headers. They can easily be installed by
+using the distro package manager. For example, on Debian amd Ubuntu:
+
+    $ sudo apt-get install gcc python-dev
+
+...on Redhat and CentOS:
+
+    $ sudo yum install gcc python-devel
+
+Once done, you can build/install psutil with:
+
+    $ python setup.py install
+
+
+==================
+Installing on OS X
+==================
+
+OS X installation from source will require gcc which you can obtain as part of
+the 'XcodeTools' installer from Apple. Then you can run the standard distutils
+commands.
+To build only:
+
+    $ python setup.py build
+
+To install and build:
+
+    $ python setup.py install
+
+
+=====================
+Installing on FreeBSD
+=====================
+
+The same compiler used to install Python must be present on the system in order
+to build modules using distutils. Assuming it is installed, you can build using
+the standard distutils commands.
+
+Build only:
+
+    $ python setup.py build
+
+Install and build:
+
+    $ python setup.py install
+
+
+========
+Makefile
+========
+
+A makefile is available for both UNIX and Windows (make.bat).  It provides
+some automations for the tasks described above and might be preferred over
+using setup.py. With it you can::
+
+    $ make install    # just install
+    $ make uninstall  # uninstall (needs pip)
+    $ make test       # run tests
+    $ make clean      # remove installation files
--- a/python/psutil/MANIFEST.in
+++ b/python/psutil/MANIFEST.in
@@ -1,10 +1,17 @@
+include .travis.yml
 include CREDITS
-include HISTORY
+include HISTORY.rst
+include INSTALL.rst
 include LICENSE
+include make.bat
+include Makefile
 include MANIFEST.in
-include README
-include TODO
+include README.rst
 include setup.py
+include TODO
+include tox.ini
+recursive-include docs *
+recursive-exclude docs/_build *
+recursive-include examples *.py
 recursive-include psutil *.py *.c *.h
-recursive-include test *.py
-recursive-include examples *.py
+recursive-include test *.py README
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/python/psutil/Makefile
@@ -0,0 +1,90 @@
+# Shortcuts for various tasks (UNIX only).
+# To use a specific Python version run:
+# $ make install PYTHON=python3.3
+
+# You can set these variables from the command line.
+PYTHON    = python
+TSCRIPT   = test/test_psutil.py
+
+all: test
+
+clean:
+	rm -f `find . -type f -name \*.py[co]`
+	rm -f `find . -type f -name \*.so`
+	rm -f `find . -type f -name .\*~`
+	rm -f `find . -type f -name \*.orig`
+	rm -f `find . -type f -name \*.bak`
+	rm -f `find . -type f -name \*.rej`
+	rm -rf `find . -type d -name __pycache__`
+	rm -rf *.egg-info
+	rm -rf *\$testfile*
+	rm -rf .tox
+	rm -rf build
+	rm -rf dist
+	rm -rf docs/_build
+
+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
+
+uninstall:
+	if test $(PYTHON) = python2.4; then \
+		pip-2.4 uninstall -y -v psutil; \
+	else \
+		cd ..; $(PYTHON) -m pip uninstall -y -v psutil; \
+	fi
+
+test: install
+	$(PYTHON) $(TSCRIPT)
+
+test-process: install
+	$(PYTHON) -m unittest -v test.test_psutil.TestProcess
+
+test-system: install
+	$(PYTHON) -m unittest -v test.test_psutil.TestSystemAPIs
+
+test-memleaks: install
+	$(PYTHON) -m unittest -v test.test_memory_leaks
+
+# Run a specific test by name; e.g. "make test-by-name disk_" will run
+# all test methods containing "disk_" in their name.
+# Requires "pip install nose".
+test-by-name:
+	@$(PYTHON) -m nose test/test_psutil.py --nocapture -v -m $(filter-out $@,$(MAKECMDGOALS))
+
+# requires "pip install pep8"
+pep8:
+	@git ls-files | grep \\.py$ | xargs pep8
+
+# requires "pip install pyflakes"
+pyflakes:
+	@export PYFLAKES_NODOCTEST=1 && \
+		git ls-files | grep \\.py$ | xargs pyflakes
+
+# requires "pip install flake8"
+flake8:
+	@git ls-files | grep \\.py$ | xargs flake8
+
+
+# Upload source tarball on https://pypi.python.org/pypi/psutil.
+upload-src: clean
+	$(PYTHON) setup.py sdist upload
+
+# Build and upload doc on https://pythonhosted.org/psutil/.
+# Requires "pip install sphinx-pypi-upload".
+upload-doc:
+	cd docs; make html
+	$(PYTHON) setup.py upload_sphinx --upload-dir=docs/_build/html
+
+# git-tag a new release
+git-tag-release:
+	git tag -a release-`python -c "import setup; print(setup.get_version())"` -m `git rev-list HEAD --count`:`git rev-parse --short HEAD`
+	echo "done; now run 'git push --follow-tags' to push the new tag on the remote repo"
--- a/python/psutil/PKG-INFO
+++ b/python/psutil/PKG-INFO
@@ -1,263 +1,399 @@
 Metadata-Version: 1.1
 Name: psutil
-Version: 1.0.1
-Summary: A process and system utilities module for Python
-Home-page: http://code.google.com/p/psutil/
+Version: 2.1.3
+Summary: psutil is a cross-platform library for retrieving information onrunning processes and system utilization (CPU, memory, disks, network)in Python.
+Home-page: https://github.com/giampaolo/psutil
 Author: Giampaolo Rodola
 Author-email: g.rodola <at> gmail <dot> com
-License: License :: OSI Approved :: BSD License
-Download-URL: http://psutil.googlecode.com/files/psutil-1.0.1.tar.gz
-Description: ===========
+License: BSD
+Description: .. image:: https://pypip.in/d/psutil/badge.png
+            :target: https://crate.io/packages/psutil/
+            :alt: Download this month
+        
+        .. image:: https://pypip.in/v/psutil/badge.png
+            :target: https://pypi.python.org/pypi/psutil/
+            :alt: Latest version
+        
+        .. image:: https://pypip.in/license/psutil/badge.png
+            :target: https://pypi.python.org/pypi/psutil/
+            :alt: License
+        
+        .. image:: https://api.travis-ci.org/giampaolo/psutil.png?branch=master
+            :target: https://travis-ci.org/giampaolo/psutil
+            :alt: Travis
+        
+        ===========
         Quick links
         ===========
         
-        * `Home page <http://code.google.com/p/psutil>`_
-        * `Download <http://code.google.com/p/psutil/downloads/list>`_
-        * `Documentation <http://code.google.com/p/psutil/wiki/Documentation>`_
+        - `Home page <https://github.com/giampaolo/psutil>`_
+        - `Documentation <http://pythonhosted.org/psutil/>`_
+        - `Download <https://pypi.python.org/pypi?:action=display&name=psutil#downloads>`_
+        - `Forum <http://groups.google.com/group/psutil/topics>`_
+        - `Blog <http://grodola.blogspot.com/search/label/psutil>`_
+        - `What's new <https://github.com/giampaolo/psutil/blob/master/HISTORY.rst>`_
         
         =======
         Summary
         =======
         
-        psutil is a module providing an interface for retrieving information on all
-        running processes and system utilization (CPU, memory, disks, network, users) in
-        a portable way by using Python, implementing many functionalities offered by
-        command line tools such as:  **ps, top, df, kill, free, lsof, free, netstat,
-        ifconfig, nice, ionice, iostat, iotop, uptime, pidof, tty, who, taskset, pmap**.
+        psutil (python system and process 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, OSX, FreeBSD** and **Sun Solaris**, both **32-bit** and
+        **64-bit** architectures, with Python versions from **2.4 to 3.4**. PyPy is
+        also known to work.
+        
+        ====================
+        Example applications
+        ====================
         
-        It currently supports **Linux**, **Windows**, **OSX**, **FreeBSD**,
-        **Sun Solaris** both **32-bit** and **64-bit** with Python versions from **2.4**
-        to **3.3** by using a single code base.
+        .. image:: http://psutil.googlecode.com/svn/wiki/images/top-thumb.png
+            :target: http://psutil.googlecode.com/svn/wiki/images/top.png
+            :alt: top
+        
+        .. image:: http://psutil.googlecode.com/svn/wiki/images/nettop-thumb.png
+            :target: http://psutil.googlecode.com/svn/wiki/images/nettop.png
+            :alt: nettop
+        
+        .. image:: http://psutil.googlecode.com/svn/wiki/images/iotop-thumb.png
+            :target: http://psutil.googlecode.com/svn/wiki/images/iotop.png
+            :alt: iotop
+        
+        See also:
+        
+         * https://github.com/nicolargo/glances
+         * https://github.com/Jahaja/psdash
+         * https://code.google.com/p/grr/
         
         ==============
         Example usages
         ==============
         
         CPU
         ===
         
-        >>> import psutil
-        >>> psutil.cpu_times()
-        cputimes(user=3961.46, nice=169.729, system=2150.659, idle=16900.540,
-                 iowait=629.509, irq=0.0, softirq=19.422, 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]
-        [7.0, 8.5]
-        [1.2, 9.0]
-        >>>
-        >>> for x in range(3):
-        ...     psutil.cpu_times_percent(interval=1, percpu=False)
-        ...
-        cpupercent(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)
-        cpupercent(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)
-        cpupercent(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)
+        .. 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
+            >>>
         
         Memory
         ======
         
-        >>> psutil.virtual_memory()
-        vmem(total=8374149120L, available=2081050624L, percent=75.1, used=8074080256L,
-             free=300068864L, active=3294920704, inactive=1361616896, buffers=529895424L,
-             cached=1251086336)
-        >>> psutil.swap_memory()
-        swap(total=2097147904L, used=296128512L, free=1801019392L, percent=14.1,
-             sin=304193536, sout=677842944)
-        >>>
+        .. code-block:: python
         
+            >>> psutil.virtual_memory()
+            svmem(total=8374149120L, available=2081050624L, percent=75.1, used=8074080256L, free=300068864L, active=3294920704, inactive=1361616896, buffers=529895424L, cached=1251086336)
+            >>> psutil.swap_memory()
+            sswap(total=2097147904L, used=296128512L, free=1801019392L, percent=14.1, sin=304193536, sout=677842944)
+            >>>
         
         Disks
         =====
         
-        >>> psutil.disk_partitions()
-        [partition(device='/dev/sda1', mountpoint='/', fstype='ext4', opts='rw,nosuid'),
-         partition(device='/dev/sda2', mountpoint='/home', fstype='ext, opts='rw')]
-        >>>
-        >>> psutil.disk_usage('/')
-        usage(total=21378641920, used=4809781248, free=15482871808, percent=22.5)
-        >>>
-        >>> psutil.disk_io_counters()
-        iostat(read_count=719566, write_count=1082197, read_bytes=18626220032,
-               write_bytes=24081764352, read_time=5023392, write_time=63199568)
-        >>>
+        .. 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)
+            >>>
         
         Network
         =======
         
-        >>> psutil.net_io_counters(pernic=True)
-        {'lo': iostat(bytes_sent=799953745, bytes_recv=799953745,
-                      packets_sent=453698, packets_recv=453698),
-         'eth0': iostat(bytes_sent=734324837, bytes_recv=4163935363,
-                        packets_sent=3605828, packets_recv=4096685)}
-        >>>
+        .. 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()
+            [pconn(fd=115, family=2, type=1, laddr=('10.0.0.1', 48776), raddr=('93.186.135.91', 80), status='ESTABLISHED', pid=1254),
+             pconn(fd=117, family=2, type=1, laddr=('10.0.0.1', 43761), raddr=('72.14.234.100', 80), status='CLOSING', pid=2987),
+             pconn(fd=-1, family=2, type=1, laddr=('10.0.0.1', 60759), raddr=('72.14.234.104', 80), status='ESTABLISHED', pid=None),
+             pconn(fd=-1, family=2, type=1, laddr=('10.0.0.1', 51314), raddr=('72.14.234.83', 443), status='SYN_SENT', pid=None)
+             ...]
         
         Other system info
         =================
         
-        >>> psutil.get_users()
-        [user(name='giampaolo', terminal='pts/2', host='localhost', started=1340737536.0),
-         user(name='giampaolo', terminal='pts/3', host='localhost', started=1340737792.0)]
-        >>>
-        >>> psutil.get_boot_time()
-        1365519115.0
+        .. code-block:: python
         
+            >>> psutil.users()
+            [user(name='giampaolo', terminal='pts/2', host='localhost', started=1340737536.0),
+             user(name='giampaolo', terminal='pts/3', host='localhost', started=1340737792.0)]
+            >>>
+            >>> psutil.boot_time()
+            1365519115.0
+            >>>
         
         Process management
         ==================
         
-        >>> import psutil
-        >>> psutil.get_pid_list()
-        [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.name
-        'python'
-        >>> p.exe
-        '/usr/bin/python'
-        >>> p.getcwd()
-        '/home/giampaolo'
-        >>> p.cmdline
-        ['/usr/bin/python', 'main.py']
-        >>>
-        >>> str(p.status)
-        'running'
-        >>> p.username
-        'giampaolo'
-        >>> p.create_time
-        1267551141.5019531
-        >>> p.terminal
-        '/dev/pts/0'
-        >>>
-        >>> p.uids
-        user(real=1000, effective=1000, saved=1000)
-        >>> p.gids
-        group(real=1000, effective=1000, saved=1000)
-        >>>
-        >>> p.get_cpu_times()
-        cputimes(user=1.02, system=0.31)
-        >>> p.get_cpu_percent(interval=1.0)
-        12.1
-        >>> p.get_cpu_affinity()
-        [0, 1, 2, 3]
-        >>> p.set_cpu_affinity([0])
-        >>>
-        >>> p.get_memory_percent()
-        0.63423
-        >>>
-        >>> p.get_memory_info()
-        meminfo(rss=7471104, vms=68513792)
-        >>> p.get_ext_memory_info()
-        meminfo(rss=9662464, vms=49192960, shared=3612672, text=2564096, lib=0, data=5754880, dirty=0)
-        >>> p.get_memory_maps()
-        [mmap(path='/lib/x86_64-linux-gnu/libutil-2.15.so', rss=16384, anonymous=8192, swap=0),
-         mmap(path='/lib/x86_64-linux-gnu/libc-2.15.so', rss=6384, anonymous=15, swap=0),
-         mmap(path='/lib/x86_64-linux-gnu/libcrypto.so.1.0.0', rss=34124, anonymous=1245, swap=0),
-         mmap(path='[heap]', rss=54653, anonymous=8192, swap=0),
-         mmap(path='[stack]', rss=1542, anonymous=166, swap=0),
-         ...]
-        >>>
-        >>> p.get_io_counters()
-        io(read_count=478001, write_count=59371, read_bytes=700416, write_bytes=69632)
-        >>>
-        >>> p.get_open_files()
-        [openfile(path='/home/giampaolo/svn/psutil/somefile', fd=3)]
-        >>>
-        >>> p.get_connections()
-        [connection(fd=115, family=2, type=1, laddr=('10.0.0.1', 48776),
-                    raddr=('93.186.135.91', 80), status='ESTABLISHED'),
-         connection(fd=117, family=2, type=1, laddr=('10.0.0.1', 43761),
-                    raddr=('72.14.234.100', 80), status='CLOSING'),
-         connection(fd=119, family=2, type=1, laddr=('10.0.0.1', 60759),
-                    raddr=('72.14.234.104', 80), status='ESTABLISHED'),
-         connection(fd=123, family=2, type=1, laddr=('10.0.0.1', 51314),
-                    raddr=('72.14.234.83', 443), status='SYN_SENT')]
-        >>>
-        >>> p.get_num_threads()
-        4
-        >>> p.get_num_fds()
-        8
-        >>> p.get_threads()
-        [thread(id=5234, user_time=22.5, system_time=9.2891),
-         thread(id=5235, user_time=0.0, system_time=0.0),
-         thread(id=5236, user_time=0.0, system_time=0.0),
-         thread(id=5237, user_time=0.0707, system_time=1.1)]
-        >>>
-        >>> p.get_num_ctx_switches()
-        amount(voluntary=78, involuntary=19)
-        >>>
-        >>> p.get_nice()
-        0
-        >>> p.set_nice(10)
-        >>>
-        >>> p.suspend()
-        >>> p.resume()
-        >>>
-        >>> p.terminate()
-        >>> 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
-        root           3  0.0  0.0       0       0 ?          Jun17   00:05  ksoftirqd/0
-        ...
-        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
-        >>>
+        .. code-block:: python
         
-Keywords: ps,top,kill,free,lsof,netstat,nice,tty,ionice,uptime,taskmgr,process,df,iotop,iostat,ifconfig,taskset,who,pidof,pmap,smem,monitoring
+            >>> 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.name()
+            'python'
+            >>> p.exe()
+            '/usr/bin/python'
+            >>> p.cwd()
+            '/home/giampaolo'
+            >>> p.cmdline()
+            ['/usr/bin/python', 'main.py']
+            >>>
+            >>> 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)
+            >>> p.cpu_percent(interval=1.0)
+            12.1
+            >>> p.cpu_affinity()
+            [0, 1, 2, 3]
+            >>> p.cpu_affinity([0])  # set
+            >>>
+            >>> p.memory_percent()
+            0.63423
+            >>>
+            >>> p.memory_info()
+            pmem(rss=7471104, vms=68513792)
+            >>> p.ext_memory_info()
+            extmem(rss=9662464, vms=49192960, shared=3612672, text=2564096, lib=0, data=5754880, dirty=0)
+            >>> p.memory_maps()
+            [pmmap_grouped(path='/lib/x86_64-linux-gnu/libutil-2.15.so', rss=16384, anonymous=8192, swap=0),
+             pmmap_grouped(path='/lib/x86_64-linux-gnu/libc-2.15.so', rss=6384, anonymous=15, swap=0),
+             pmmap_grouped(path='/lib/x86_64-linux-gnu/libcrypto.so.1.0.0', rss=34124, anonymous=1245, swap=0),
+             pmmap_grouped(path='[heap]', rss=54653, anonymous=8192, swap=0),
+             pmmap_grouped(path='[stack]', rss=1542, anonymous=166, swap=0),
+             ...]
+            >>>
+            >>> p.io_counters()
+            pio(read_count=478001, write_count=59371, read_bytes=700416, write_bytes=69632)
+            >>>
+            >>> p.open_files()
+            [popenfile(path='/home/giampaolo/svn/psutil/somefile', fd=3)]
+            >>>
+            >>> p.connections()
+            [pconn(fd=115, family=2, type=1, laddr=('10.0.0.1', 48776), raddr=('93.186.135.91', 80), status='ESTABLISHED'),
+             pconn(fd=117, family=2, type=1, laddr=('10.0.0.1', 43761), raddr=('72.14.234.100', 80), status='CLOSING'),
+             pconn(fd=119, family=2, type=1, laddr=('10.0.0.1', 60759), raddr=('72.14.234.104', 80), status='ESTABLISHED'),
+             pconn(fd=123, family=2, type=1, laddr=('10.0.0.1', 51314), raddr=('72.14.234.83', 443), status='SYN_SENT')]
+            >>>
+            >>> p.num_threads()
+            4
+            >>> p.num_fds()
+            8
+            >>> p.threads()
+            [pthread(id=5234, user_time=22.5, system_time=9.2891),
+             pthread(id=5235, user_time=0.0, system_time=0.0),
+             pthread(id=5236, user_time=0.0, system_time=0.0),
+             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=3, value=0)
+            >>>
+            >>> p.rlimit(psutil.RLIMIT_NOFILE, (5, 5))  # set resource limits (Linux only)
+            >>> p.rlimit(psutil.RLIMIT_NOFILE)
+            (5, 5)
+            >>>
+            >>> p.suspend()
+            >>> p.resume()
+            >>>
+            >>> p.terminate()
+            >>> 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
+            root           3  0.0  0.0       0       0            Jun17   00:05  ksoftirqd/0
+            ...
+            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
+        
+            >>> for p in psutil.process_iter():
+            ...     print(p)
+            ...
+            psutil.Process(pid=1, name='init')
+            psutil.Process(pid=2, name='kthreadd')
+            psutil.Process(pid=3, name='ksoftirqd/0')
+            ...
+            >>>
+            >>> def on_terminate(proc):
+            ...     print("process {} terminated".format(proc))
+            ...
+            >>> # waits for multiple processes to terminate
+            >>> gone, alive = psutil.wait_procs(procs_list, 3, callback=on_terminate)
+            >>>
+        
+        ======
+        Donate
+        ======
+        
+        A lot of time and effort went into making psutil as it is right now.
+        If you feel psutil is useful to you or your business and want to support its future development please consider donating me (`Giampaolo Rodola' <http://grodola.blogspot.com/p/about.html>`_) some money.
+        I only ask for a small donation, but of course I appreciate any amount.
+        
+        .. image:: http://www.paypal.com/en_US/i/btn/x-click-but04.gif
+            :target: https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=A9ZS7PKKRM3S8
+            :alt: Donate via PayPal
+        
+        Don't want to donate money? Then maybe you could `write me a recommendation on Linkedin <http://www.linkedin.com/in/grodola>`_.
+        
+        ============
+        Mailing list
+        ============
+        
+        http://groups.google.com/group/psutil/
+        
+        ========
+        Timeline
+        ========
+        
+        - 2014-09-26: `psutil-2.1.3.tar.gz <https://pypi.python.org/packages/source/p/psutil/psutil-2.1.3.tar.gz>`_
+        - 2014-09-21: `psutil-2.1.2.tar.gz <https://pypi.python.org/packages/source/p/psutil/psutil-2.1.2.tar.gz>`_
+        - 2014-04-30: `psutil-2.1.1.tar.gz <https://pypi.python.org/packages/source/p/psutil/psutil-2.1.1.tar.gz>`_
+        - 2014-04-08: `psutil-2.1.0.tar.gz <https://pypi.python.org/packages/source/p/psutil/psutil-2.1.0.tar.gz>`_
+        - 2014-03-10: `psutil-2.0.0.tar.gz <https://pypi.python.org/packages/source/p/psutil/psutil-2.0.0.tar.gz>`_
+        - 2013-11-25: `psutil-1.2.1.tar.gz <https://pypi.python.org/packages/source/p/psutil/psutil-1.2.1.tar.gz>`_
+        - 2013-11-20: `psutil-1.2.0.tar.gz <https://pypi.python.org/packages/source/p/psutil/psutil-1.2.0.tar.gz>`_
+        - 2013-11-07: `psutil-1.1.3.tar.gz <https://pypi.python.org/packages/source/p/psutil/psutil-1.1.3.tar.gz>`_
+        - 2013-10-22: `psutil-1.1.2.tar.gz <https://pypi.python.org/packages/source/p/psutil/psutil-1.1.2.tar.gz>`_
+        - 2013-10-08: `psutil-1.1.1.tar.gz <https://pypi.python.org/packages/source/p/psutil/psutil-1.1.1.tar.gz>`_
+        - 2013-09-28: `psutil-1.1.0.tar.gz <https://pypi.python.org/packages/source/p/psutil/psutil-1.1.0.tar.gz>`_
+        - 2013-07-12: `psutil-1.0.1.tar.gz <https://pypi.python.org/packages/source/p/psutil/psutil-1.0.1.tar.gz>`_
+        - 2013-07-10: `psutil-1.0.0.tar.gz <https://pypi.python.org/packages/source/p/psutil/psutil-1.0.0.tar.gz>`_
+        - 2013-05-03: `psutil-0.7.1.tar.gz <https://pypi.python.org/packages/source/p/psutil/psutil-0.7.1.tar.gz>`_
+        - 2013-04-12: `psutil-0.7.0.tar.gz <https://pypi.python.org/packages/source/p/psutil/psutil-0.7.0.tar.gz>`_
+        - 2012-08-16: `psutil-0.6.1.tar.gz <https://pypi.python.org/packages/source/p/psutil/psutil-0.6.1.tar.gz>`_
+        - 2012-08-13: `psutil-0.6.0.tar.gz <https://pypi.python.org/packages/source/p/psutil/psutil-0.6.0.tar.gz>`_
+        - 2012-06-29: `psutil-0.5.1.tar.gz <https://pypi.python.org/packages/source/p/psutil/psutil-0.5.1.tar.gz>`_
+        - 2012-06-27: `psutil-0.5.0.tar.gz <https://pypi.python.org/packages/source/p/psutil/psutil-0.5.0.tar.gz>`_
+        - 2011-12-14: `psutil-0.4.1.tar.gz <https://pypi.python.org/packages/source/p/psutil/psutil-0.4.1.tar.gz>`_
+        - 2011-10-29: `psutil-0.4.0.tar.gz <https://pypi.python.org/packages/source/p/psutil/psutil-0.4.0.tar.gz>`_
+        - 2011-07-08: `psutil-0.3.0.tar.gz <https://pypi.python.org/packages/source/p/psutil/psutil-0.3.0.tar.gz>`_
+        - 2011-03-20: `psutil-0.2.1.tar.gz <https://pypi.python.org/packages/source/p/psutil/psutil-0.2.1.tar.gz>`_
+        - 2010-11-13: `psutil-0.2.0.tar.gz <https://pypi.python.org/packages/source/p/psutil/psutil-0.2.0.tar.gz>`_
+        - 2010-03-02: `psutil-0.1.3.tar.gz <https://pypi.python.org/packages/source/p/psutil/psutil-0.1.3.tar.gz>`_
+        - 2009-05-06: `psutil-0.1.2.tar.gz <https://pypi.python.org/packages/source/p/psutil/psutil-0.1.2.tar.gz>`_
+        - 2009-03-06: `psutil-0.1.1.tar.gz <https://pypi.python.org/packages/source/p/psutil/psutil-0.1.1.tar.gz>`_
+        - 2009-01-27: `psutil-0.1.0.tar.gz <https://pypi.python.org/packages/source/p/psutil/psutil-0.1.0.tar.gz>`_
+        
+Keywords: ps,top,kill,free,lsof,netstat,nice,tty,ionice,uptime,taskmgr,process,df,iotop,iostat,ifconfig,taskset,who,pidof,pmap,smem,monitoring,ulimit,prlimit
 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 NT/2000
 Classifier: Operating System :: Microsoft
-Classifier: Operating System :: Microsoft :: Windows :: Windows NT/2000
-Classifier: Operating System :: POSIX
+Classifier: Operating System :: OS Independent
+Classifier: Operating System :: POSIX :: BSD :: FreeBSD
 Classifier: Operating System :: POSIX :: Linux
-Classifier: Operating System :: POSIX :: BSD :: FreeBSD
 Classifier: Operating System :: POSIX :: SunOS/Solaris
-Classifier: Operating System :: OS Independent
+Classifier: Operating System :: POSIX
 Classifier: Programming Language :: C
-Classifier: Programming Language :: Python
 Classifier: Programming Language :: Python :: 2
 Classifier: Programming Language :: Python :: 2.4
 Classifier: Programming Language :: Python :: 2.5
 Classifier: Programming Language :: Python :: 2.6
 Classifier: Programming Language :: Python :: 2.7
 Classifier: Programming Language :: Python :: 3
 Classifier: Programming Language :: Python :: 3.0
 Classifier: Programming Language :: Python :: 3.1
 Classifier: Programming Language :: Python :: 3.2
 Classifier: Programming Language :: Python :: 3.3
-Classifier: Topic :: System :: Monitoring
-Classifier: Topic :: System :: Networking
-Classifier: Topic :: System :: Networking :: Monitoring
+Classifier: Programming Language :: Python :: 3.4
+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
+Classifier: Topic :: System :: Monitoring
+Classifier: Topic :: System :: Networking :: Monitoring
+Classifier: Topic :: System :: Networking
 Classifier: Topic :: System :: Systems Administration
 Classifier: Topic :: Utilities
-Classifier: Topic :: Software Development :: Libraries
-Classifier: Topic :: Software Development :: Libraries :: Python Modules
-Classifier: Intended Audience :: Developers
-Classifier: Intended Audience :: System Administrators
-Classifier: License :: OSI Approved :: BSD License
deleted file mode 100644
--- a/python/psutil/README
+++ /dev/null
@@ -1,217 +0,0 @@
-===========
-Quick links
-===========
-
-* `Home page <http://code.google.com/p/psutil>`_
-* `Download <http://code.google.com/p/psutil/downloads/list>`_
-* `Documentation <http://code.google.com/p/psutil/wiki/Documentation>`_
-
-=======
-Summary
-=======
-
-psutil is a module providing an interface for retrieving information on all
-running processes and system utilization (CPU, memory, disks, network, users) in
-a portable way by using Python, implementing many functionalities offered by
-command line tools such as:  **ps, top, df, kill, free, lsof, free, netstat,
-ifconfig, nice, ionice, iostat, iotop, uptime, pidof, tty, who, taskset, pmap**.
-
-It currently supports **Linux**, **Windows**, **OSX**, **FreeBSD**,
-**Sun Solaris** both **32-bit** and **64-bit** with Python versions from **2.4**
-to **3.3** by using a single code base.
-
-==============
-Example usages
-==============
-
-CPU
-===
-
->>> import psutil
->>> psutil.cpu_times()
-cputimes(user=3961.46, nice=169.729, system=2150.659, idle=16900.540,
-         iowait=629.509, irq=0.0, softirq=19.422, 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]
-[7.0, 8.5]
-[1.2, 9.0]
->>>
->>> for x in range(3):
-...     psutil.cpu_times_percent(interval=1, percpu=False)
-...
-cpupercent(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)
-cpupercent(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)
-cpupercent(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)
-
-Memory
-======
-
->>> psutil.virtual_memory()
-vmem(total=8374149120L, available=2081050624L, percent=75.1, used=8074080256L,
-     free=300068864L, active=3294920704, inactive=1361616896, buffers=529895424L,
-     cached=1251086336)
->>> psutil.swap_memory()
-swap(total=2097147904L, used=296128512L, free=1801019392L, percent=14.1,
-     sin=304193536, sout=677842944)
->>>
-
-
-Disks
-=====
-
->>> psutil.disk_partitions()
-[partition(device='/dev/sda1', mountpoint='/', fstype='ext4', opts='rw,nosuid'),
- partition(device='/dev/sda2', mountpoint='/home', fstype='ext, opts='rw')]
->>>
->>> psutil.disk_usage('/')
-usage(total=21378641920, used=4809781248, free=15482871808, percent=22.5)
->>>
->>> psutil.disk_io_counters()
-iostat(read_count=719566, write_count=1082197, read_bytes=18626220032,
-       write_bytes=24081764352, read_time=5023392, write_time=63199568)
->>>
-
-
-Network
-=======
-
->>> psutil.net_io_counters(pernic=True)
-{'lo': iostat(bytes_sent=799953745, bytes_recv=799953745,
-              packets_sent=453698, packets_recv=453698),
- 'eth0': iostat(bytes_sent=734324837, bytes_recv=4163935363,
-                packets_sent=3605828, packets_recv=4096685)}
->>>
-
-Other system info
-=================
-
->>> psutil.get_users()
-[user(name='giampaolo', terminal='pts/2', host='localhost', started=1340737536.0),
- user(name='giampaolo', terminal='pts/3', host='localhost', started=1340737792.0)]
->>>
->>> psutil.get_boot_time()
-1365519115.0
-
-
-Process management
-==================
-
->>> import psutil
->>> psutil.get_pid_list()
-[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.name
-'python'
->>> p.exe
-'/usr/bin/python'
->>> p.getcwd()
-'/home/giampaolo'
->>> p.cmdline
-['/usr/bin/python', 'main.py']
->>>
->>> str(p.status)
-'running'
->>> p.username
-'giampaolo'
->>> p.create_time
-1267551141.5019531
->>> p.terminal
-'/dev/pts/0'
->>>
->>> p.uids
-user(real=1000, effective=1000, saved=1000)
->>> p.gids
-group(real=1000, effective=1000, saved=1000)
->>>
->>> p.get_cpu_times()
-cputimes(user=1.02, system=0.31)
->>> p.get_cpu_percent(interval=1.0)
-12.1
->>> p.get_cpu_affinity()
-[0, 1, 2, 3]
->>> p.set_cpu_affinity([0])
->>>
->>> p.get_memory_percent()
-0.63423
->>>
->>> p.get_memory_info()
-meminfo(rss=7471104, vms=68513792)
->>> p.get_ext_memory_info()
-meminfo(rss=9662464, vms=49192960, shared=3612672, text=2564096, lib=0, data=5754880, dirty=0)
->>> p.get_memory_maps()
-[mmap(path='/lib/x86_64-linux-gnu/libutil-2.15.so', rss=16384, anonymous=8192, swap=0),
- mmap(path='/lib/x86_64-linux-gnu/libc-2.15.so', rss=6384, anonymous=15, swap=0),
- mmap(path='/lib/x86_64-linux-gnu/libcrypto.so.1.0.0', rss=34124, anonymous=1245, swap=0),
- mmap(path='[heap]', rss=54653, anonymous=8192, swap=0),
- mmap(path='[stack]', rss=1542, anonymous=166, swap=0),
- ...]
->>>
->>> p.get_io_counters()
-io(read_count=478001, write_count=59371, read_bytes=700416, write_bytes=69632)
->>>
->>> p.get_open_files()
-[openfile(path='/home/giampaolo/svn/psutil/somefile', fd=3)]
->>>
->>> p.get_connections()
-[connection(fd=115, family=2, type=1, laddr=('10.0.0.1', 48776),
-            raddr=('93.186.135.91', 80), status='ESTABLISHED'),
- connection(fd=117, family=2, type=1, laddr=('10.0.0.1', 43761),
-            raddr=('72.14.234.100', 80), status='CLOSING'),
- connection(fd=119, family=2, type=1, laddr=('10.0.0.1', 60759),
-            raddr=('72.14.234.104', 80), status='ESTABLISHED'),
- connection(fd=123, family=2, type=1, laddr=('10.0.0.1', 51314),
-            raddr=('72.14.234.83', 443), status='SYN_SENT')]
->>>
->>> p.get_num_threads()
-4
->>> p.get_num_fds()
-8
->>> p.get_threads()
-[thread(id=5234, user_time=22.5, system_time=9.2891),
- thread(id=5235, user_time=0.0, system_time=0.0),
- thread(id=5236, user_time=0.0, system_time=0.0),
- thread(id=5237, user_time=0.0707, system_time=1.1)]
->>>
->>> p.get_num_ctx_switches()
-amount(voluntary=78, involuntary=19)
->>>
->>> p.get_nice()
-0
->>> p.set_nice(10)
->>>
->>> p.suspend()
->>> p.resume()
->>>
->>> p.terminate()
->>> 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
-root           3  0.0  0.0       0       0 ?          Jun17   00:05  ksoftirqd/0
-...
-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
->>>
new file mode 100644
--- /dev/null
+++ b/python/psutil/README.rst
@@ -0,0 +1,349 @@
+.. image:: https://pypip.in/d/psutil/badge.png
+    :target: https://crate.io/packages/psutil/
+    :alt: Download this month
+
+.. image:: https://pypip.in/v/psutil/badge.png
+    :target: https://pypi.python.org/pypi/psutil/
+    :alt: Latest version
+
+.. image:: https://pypip.in/license/psutil/badge.png
+    :target: https://pypi.python.org/pypi/psutil/
+    :alt: License
+
+.. image:: https://api.travis-ci.org/giampaolo/psutil.png?branch=master
+    :target: https://travis-ci.org/giampaolo/psutil
+    :alt: Travis
+
+===========
+Quick links
+===========
+
+- `Home page <https://github.com/giampaolo/psutil>`_
+- `Documentation <http://pythonhosted.org/psutil/>`_
+- `Download <https://pypi.python.org/pypi?:action=display&name=psutil#downloads>`_
+- `Forum <http://groups.google.com/group/psutil/topics>`_
+- `Blog <http://grodola.blogspot.com/search/label/psutil>`_
+- `What's new <https://github.com/giampaolo/psutil/blob/master/HISTORY.rst>`_
+
+=======
+Summary
+=======
+
+psutil (python system and process 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, OSX, FreeBSD** and **Sun Solaris**, both **32-bit** and
+**64-bit** architectures, with Python versions from **2.4 to 3.4**. PyPy is
+also known to work.
+
+====================
+Example applications
+====================
+
+.. image:: http://psutil.googlecode.com/svn/wiki/images/top-thumb.png
+    :target: http://psutil.googlecode.com/svn/wiki/images/top.png
+    :alt: top
+
+.. image:: http://psutil.googlecode.com/svn/wiki/images/nettop-thumb.png
+    :target: http://psutil.googlecode.com/svn/wiki/images/nettop.png
+    :alt: nettop
+
+.. image:: http://psutil.googlecode.com/svn/wiki/images/iotop-thumb.png
+    :target: http://psutil.googlecode.com/svn/wiki/images/iotop.png
+    :alt: iotop
+
+See also:
+
+ * https://github.com/nicolargo/glances
+ * https://github.com/Jahaja/psdash
+ * https://code.google.com/p/grr/
+
+==============
+Example usages
+==============
+
+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
+    >>>
+
+Memory
+======
+
+.. code-block:: python
+
+    >>> psutil.virtual_memory()
+    svmem(total=8374149120L, available=2081050624L, percent=75.1, used=8074080256L, free=300068864L, active=3294920704, inactive=1361616896, buffers=529895424L, cached=1251086336)
+    >>> psutil.swap_memory()
+    sswap(total=2097147904L, used=296128512L, free=1801019392L, 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)
+    >>>
+
+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()
+    [pconn(fd=115, family=2, type=1, laddr=('10.0.0.1', 48776), raddr=('93.186.135.91', 80), status='ESTABLISHED', pid=1254),
+     pconn(fd=117, family=2, type=1, laddr=('10.0.0.1', 43761), raddr=('72.14.234.100', 80), status='CLOSING', pid=2987),
+     pconn(fd=-1, family=2, type=1, laddr=('10.0.0.1', 60759), raddr=('72.14.234.104', 80), status='ESTABLISHED', pid=None),
+     pconn(fd=-1, family=2, type=1, laddr=('10.0.0.1', 51314), raddr=('72.14.234.83', 443), status='SYN_SENT', pid=None)
+     ...]
+
+Other system info
+=================
+
+.. code-block:: python
+
+    >>> psutil.users()
+    [user(name='giampaolo', terminal='pts/2', host='localhost', started=1340737536.0),
+     user(name='giampaolo', terminal='pts/3', host='localhost', started=1340737792.0)]
+    >>>
+    >>> 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.name()
+    'python'
+    >>> p.exe()
+    '/usr/bin/python'
+    >>> p.cwd()
+    '/home/giampaolo'
+    >>> p.cmdline()
+    ['/usr/bin/python', 'main.py']
+    >>>
+    >>> 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)
+    >>> p.cpu_percent(interval=1.0)
+    12.1
+    >>> p.cpu_affinity()
+    [0, 1, 2, 3]
+    >>> p.cpu_affinity([0])  # set
+    >>>
+    >>> p.memory_percent()
+    0.63423
+    >>>
+    >>> p.memory_info()
+    pmem(rss=7471104, vms=68513792)
+    >>> p.ext_memory_info()
+    extmem(rss=9662464, vms=49192960, shared=3612672, text=2564096, lib=0, data=5754880, dirty=0)
+    >>> p.memory_maps()
+    [pmmap_grouped(path='/lib/x86_64-linux-gnu/libutil-2.15.so', rss=16384, anonymous=8192, swap=0),
+     pmmap_grouped(path='/lib/x86_64-linux-gnu/libc-2.15.so', rss=6384, anonymous=15, swap=0),
+     pmmap_grouped(path='/lib/x86_64-linux-gnu/libcrypto.so.1.0.0', rss=34124, anonymous=1245, swap=0),
+     pmmap_grouped(path='[heap]', rss=54653, anonymous=8192, swap=0),
+     pmmap_grouped(path='[stack]', rss=1542, anonymous=166, swap=0),
+     ...]
+    >>>
+    >>> p.io_counters()
+    pio(read_count=478001, write_count=59371, read_bytes=700416, write_bytes=69632)
+    >>>
+    >>> p.open_files()
+    [popenfile(path='/home/giampaolo/svn/psutil/somefile', fd=3)]
+    >>>
+    >>> p.connections()
+    [pconn(fd=115, family=2, type=1, laddr=('10.0.0.1', 48776), raddr=('93.186.135.91', 80), status='ESTABLISHED'),
+     pconn(fd=117, family=2, type=1, laddr=('10.0.0.1', 43761), raddr=('72.14.234.100', 80), status='CLOSING'),
+     pconn(fd=119, family=2, type=1, laddr=('10.0.0.1', 60759), raddr=('72.14.234.104', 80), status='ESTABLISHED'),
+     pconn(fd=123, family=2, type=1, laddr=('10.0.0.1', 51314), raddr=('72.14.234.83', 443), status='SYN_SENT')]
+    >>>
+    >>> p.num_threads()
+    4
+    >>> p.num_fds()
+    8
+    >>> p.threads()
+    [pthread(id=5234, user_time=22.5, system_time=9.2891),
+     pthread(id=5235, user_time=0.0, system_time=0.0),
+     pthread(id=5236, user_time=0.0, system_time=0.0),
+     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=3, value=0)
+    >>>
+    >>> p.rlimit(psutil.RLIMIT_NOFILE, (5, 5))  # set resource limits (Linux only)
+    >>> p.rlimit(psutil.RLIMIT_NOFILE)
+    (5, 5)
+    >>>
+    >>> p.suspend()
+    >>> p.resume()
+    >>>
+    >>> p.terminate()
+    >>> 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
+    root           3  0.0  0.0       0       0            Jun17   00:05  ksoftirqd/0
+    ...
+    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
+
+    >>> for p in psutil.process_iter():
+    ...     print(p)
+    ...
+    psutil.Process(pid=1, name='init')
+    psutil.Process(pid=2, name='kthreadd')
+    psutil.Process(pid=3, name='ksoftirqd/0')
+    ...
+    >>>
+    >>> def on_terminate(proc):
+    ...     print("process {} terminated".format(proc))
+    ...
+    >>> # waits for multiple processes to terminate
+    >>> gone, alive = psutil.wait_procs(procs_list, 3, callback=on_terminate)
+    >>>
+
+======
+Donate
+======
+
+A lot of time and effort went into making psutil as it is right now.
+If you feel psutil is useful to you or your business and want to support its future development please consider donating me (`Giampaolo Rodola' <http://grodola.blogspot.com/p/about.html>`_) some money.
+I only ask for a small donation, but of course I appreciate any amount.
+
+.. image:: http://www.paypal.com/en_US/i/btn/x-click-but04.gif
+    :target: https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=A9ZS7PKKRM3S8
+    :alt: Donate via PayPal
+
+Don't want to donate money? Then maybe you could `write me a recommendation on Linkedin <http://www.linkedin.com/in/grodola>`_.
+
+============
+Mailing list
+============
+
+http://groups.google.com/group/psutil/
+
+========
+Timeline
+========
+
+- 2014-09-26: `psutil-2.1.3.tar.gz <https://pypi.python.org/packages/source/p/psutil/psutil-2.1.3.tar.gz>`_
+- 2014-09-21: `psutil-2.1.2.tar.gz <https://pypi.python.org/packages/source/p/psutil/psutil-2.1.2.tar.gz>`_
+- 2014-04-30: `psutil-2.1.1.tar.gz <https://pypi.python.org/packages/source/p/psutil/psutil-2.1.1.tar.gz>`_
+- 2014-04-08: `psutil-2.1.0.tar.gz <https://pypi.python.org/packages/source/p/psutil/psutil-2.1.0.tar.gz>`_
+- 2014-03-10: `psutil-2.0.0.tar.gz <https://pypi.python.org/packages/source/p/psutil/psutil-2.0.0.tar.gz>`_
+- 2013-11-25: `psutil-1.2.1.tar.gz <https://pypi.python.org/packages/source/p/psutil/psutil-1.2.1.tar.gz>`_
+- 2013-11-20: `psutil-1.2.0.tar.gz <https://pypi.python.org/packages/source/p/psutil/psutil-1.2.0.tar.gz>`_
+- 2013-11-07: `psutil-1.1.3.tar.gz <https://pypi.python.org/packages/source/p/psutil/psutil-1.1.3.tar.gz>`_
+- 2013-10-22: `psutil-1.1.2.tar.gz <https://pypi.python.org/packages/source/p/psutil/psutil-1.1.2.tar.gz>`_
+- 2013-10-08: `psutil-1.1.1.tar.gz <https://pypi.python.org/packages/source/p/psutil/psutil-1.1.1.tar.gz>`_
+- 2013-09-28: `psutil-1.1.0.tar.gz <https://pypi.python.org/packages/source/p/psutil/psutil-1.1.0.tar.gz>`_
+- 2013-07-12: `psutil-1.0.1.tar.gz <https://pypi.python.org/packages/source/p/psutil/psutil-1.0.1.tar.gz>`_
+- 2013-07-10: `psutil-1.0.0.tar.gz <https://pypi.python.org/packages/source/p/psutil/psutil-1.0.0.tar.gz>`_
+- 2013-05-03: `psutil-0.7.1.tar.gz <https://pypi.python.org/packages/source/p/psutil/psutil-0.7.1.tar.gz>`_
+- 2013-04-12: `psutil-0.7.0.tar.gz <https://pypi.python.org/packages/source/p/psutil/psutil-0.7.0.tar.gz>`_
+- 2012-08-16: `psutil-0.6.1.tar.gz <https://pypi.python.org/packages/source/p/psutil/psutil-0.6.1.tar.gz>`_
+- 2012-08-13: `psutil-0.6.0.tar.gz <https://pypi.python.org/packages/source/p/psutil/psutil-0.6.0.tar.gz>`_
+- 2012-06-29: `psutil-0.5.1.tar.gz <https://pypi.python.org/packages/source/p/psutil/psutil-0.5.1.tar.gz>`_
+- 2012-06-27: `psutil-0.5.0.tar.gz <https://pypi.python.org/packages/source/p/psutil/psutil-0.5.0.tar.gz>`_
+- 2011-12-14: `psutil-0.4.1.tar.gz <https://pypi.python.org/packages/source/p/psutil/psutil-0.4.1.tar.gz>`_
+- 2011-10-29: `psutil-0.4.0.tar.gz <https://pypi.python.org/packages/source/p/psutil/psutil-0.4.0.tar.gz>`_
+- 2011-07-08: `psutil-0.3.0.tar.gz <https://pypi.python.org/packages/source/p/psutil/psutil-0.3.0.tar.gz>`_
+- 2011-03-20: `psutil-0.2.1.tar.gz <https://pypi.python.org/packages/source/p/psutil/psutil-0.2.1.tar.gz>`_
+- 2010-11-13: `psutil-0.2.0.tar.gz <https://pypi.python.org/packages/source/p/psutil/psutil-0.2.0.tar.gz>`_
+- 2010-03-02: `psutil-0.1.3.tar.gz <https://pypi.python.org/packages/source/p/psutil/psutil-0.1.3.tar.gz>`_
+- 2009-05-06: `psutil-0.1.2.tar.gz <https://pypi.python.org/packages/source/p/psutil/psutil-0.1.2.tar.gz>`_
+- 2009-03-06: `psutil-0.1.1.tar.gz <https://pypi.python.org/packages/source/p/psutil/psutil-0.1.1.tar.gz>`_
+- 2009-01-27: `psutil-0.1.0.tar.gz <https://pypi.python.org/packages/source/p/psutil/psutil-0.1.0.tar.gz>`_
--- a/python/psutil/TODO
+++ b/python/psutil/TODO
@@ -1,95 +1,150 @@
 TODO
 ====
 
 A collection of ideas and notes about stuff to implement in future versions.
 "#NNN" occurrences refer to bug tracker issues at:
-https://code.google.com/p/psutil/issues/list
+https://github.com/giampaolo/psutil/issues
 
 
 HIGHER PRIORITY
 ===============
 
- * #387: system-wide connections (netstat).
+ * #250: net ifaces speed.
+
+ * #376: ifconfig functionalities aka psutil.net_ifaces (could be merged
+         with #250)
+
  * OpenBSD support.
 
  * #371: CPU temperature (apparently OSX and Linux only; on Linux it requires
    lm-sensors lib).
 
- * #250: net ifaces speed.
-
- * (Linux) resource limit get/set - see man prlimit.
+ * #269: expose network ifaces RX/TW queues.
 
- * Process.name on Windows is slow:
-   http://stackoverflow.com/questions/6587036/
+ * Process.threads(): thread names
 
- * Windows binary for Python 3.3 64-bit.
-
- * #269: expose network ifaces RX/TW queues.
+ * Asynchronous psutil.Popen (see http://bugs.python.org/issue1191964)
 
 
 LOWER PRIORITY
 ==============
 
  * #355: Android support.
 
  * #276: GNU/Hurd support.
 
- * NetBSD support?
+ * #429: NetBSD support.
 
- * DranflyBSD support?
+ * DragonFlyBSD support?
 
  * AIX support?
 
  * examples/pidof.py (same as 'pidof' cli tool)
 
  * examples/pstree.py (same as 'pstree' cli tool)
-    * get_threads() should also return thread names in order to implement it
+    * threads() should also return thread names in order to implement it
 
  * examples/taskmgr-gui.py (using tk).
 
- * system-wide # open file descriptors:
+ * system-wide number of open file descriptors:
     * https://jira.hyperic.com/browse/SIGAR-30
     * http://www.netadmintools.com/part295.html
 
  * Number of system threads.
     * Windows: http://msdn.microsoft.com/en-us/library/windows/desktop/ms684824(v=vs.85).aspx
 
  * #357: what CPU a process is on.
 
  * thread names:
     * https://code.google.com/p/plcrashreporter/issues/detail?id=65
 
+ * Doc / wiki which compares similarities between UNIX cli tools and psutil.
+   Example:
+   df -a  ->  psutil.disk_partitions
+   lsof   ->  psutil.Process.open_files() and psutil.Process.open_connections()
+   killall->  (actual script)
+   tty    ->  psutil.Process.terminal()
+   who    ->  psutil.users()
+
 
 DEBATABLE
 =========
 
+ * support wheels? http://pythonwheels.com/
+
+ * advanced cmdline interface exposing the whole API and providing different
+   kind of outputs (e.g. pprinted, colorized, json).
+
  * [Linux]: process cgroups (http://en.wikipedia.org/wiki/Cgroups). They look
    similar to prlimit() in terms of functionality but uglier (they should allow
    limiting per-process network IO resources though, which is great). Needs
    further reading.
 
- * cpu_percent(): current default interval is 0.1 so that by default it will
-   produce a meaningful value. It represents a trap in case the user iterates
-   over multiple processes though, as it introduces a big slowdown.
-   Should it default to 0.0?
-
- * Rename connection ntuple's fields 'local_address', 'remote_address' to
-   'laddr', 'raddr'  (note in accordance with http://bugs.python.org/issue17675)
-
- * Process per-cpus percent (XXX Windows only?), see:
-   https://groups.google.com/forum/?fromgroups#!topic/psutil/ErrKTxAbu50
-
  * Should we expose OS constants (psutil.WINDOWS, psutil.OSX etc.)?
 
  * Python 3.3. exposed different sched.h functions:
    http://docs.python.org/dev/whatsnew/3.3.html#os
    http://bugs.python.org/issue12655
    http://docs.python.org/dev/library/os.html#interface-to-the-scheduler
    It might be worth to take a look and figure out whether we can include some
    of those in psutil.
    Also, we can probably reimplement wait_pid() on POSIX which is currently
    implemented as a busy-loop.
 
  * Certain systems (XXX figure out which ones exactly) provide CPU times about
-   process children. On those systems Process.get_cpu_times() might return
+   process children. On those systems Process.cpu_times() might return
    a (user, system, user_children, system_children) ntuple.
+   Also, os.times() provides 'elapsed' times as well.
+
+ * Enrich exception classes hierarchy on Python >= 3.3 / post PEP-3151 so that:
+   - NoSuchProcess inherits from ProcessLookupError
+   - AccessDenied inherits from PermissionError
+   - TimeoutExpired inherits from TimeoutError (debatable)
+   See: http://docs.python.org/3/library/exceptions.html#os-exceptions
+
+ * Process.threads() might grow an extra "id" parameter so that it can be
+   used as such:
+
+    >>> p = psutil.Process(os.getpid())
+    >>> p.threads(id=psutil.current_thread_id())
+    thread(id=2539, user_time=0.03, system_time=0.02)
+    >>>
+
+   Note: this leads to questions such as "should we have a custom NoSuchThread
+   exception? Also see issue #418.
+
+   Note #2: this would work with os.getpid() only.
+   psutil.current_thread_id() might be desirable as per issue #418 though.
+
+  * should psutil.TimeoutExpired exception have a 'msg' kwarg similar to
+    NoSuchProcess and AccessDenied? Not that we need it, but currently we
+    cannot raise a TimeoutExpired exception with a specific error string.
+
+  * process_iter() might grow an "attrs" parameter similar to Process.as_dict()
+    invoke the necessary methods and include the results into a "cache"
+    attribute attached to the returned Process instances so that one can avoid
+    catching NSP and AccessDenied:
+        for p in process_iter(attrs=['cpu_percent']):
+            print(p.cache['cpu_percent'])
+    This also leads questions as whether we should introduce a sorting order.
+
+  * round Process.memory_percent() result?
+
+
+COMPATIBILITY BREAKAGE
+======================
+
+Removals (will likely happen in 2.2):
+
+ * (S) psutil.Process.nice  (deprecated in 0.5.0)
+ * (S) get_process_list  (deprecated in 0.5.0)
+ * (S) psutil.*mem* functions  (deprecated in 0.3.0 and 0.6.0)
+ * (M) psutil.network_io_counters  (deprecated in 1.0.0)
+ * (M) local_address and remote_address Process.connection() namedtuple fields
+       (deprecated in 1.0.0)
+
+
+REJECTED IDEAS
+==============
+
+STUB
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/python/psutil/docs/Makefile
@@ -0,0 +1,177 @@
+# Makefile for Sphinx documentation
+#
+
+# You can set these variables from the command line.
+SPHINXOPTS    =
+SPHINXBUILD   = sphinx-build
+PAPER         =
+BUILDDIR      = _build
+
+# User-friendly check for sphinx-build
+ifeq ($(shell which $(SPHINXBUILD) >/dev/null 2>&1; echo $$?), 1)
+$(error The '$(SPHINXBUILD)' command was not found. Make sure you have Sphinx installed, then set the SPHINXBUILD environment variable to point to the full path of the '$(SPHINXBUILD)' executable. Alternatively you can add the directory with the executable to your PATH. If you don't have Sphinx installed, grab it from http://sphinx-doc.org/)
+endif
+
+# Internal variables.
+PAPEROPT_a4     = -D latex_paper_size=a4
+PAPEROPT_letter = -D latex_paper_size=letter
+ALLSPHINXOPTS   = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
+# the i18n builder cannot share the environment and doctrees with the others
+I18NSPHINXOPTS  = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
+
+.PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest gettext
+
+help:
+	@echo "Please use \`make <target>' where <target> is one of"
+	@echo "  html       to make standalone HTML files"
+	@echo "  dirhtml    to make HTML files named index.html in directories"
+	@echo "  singlehtml to make a single large HTML file"
+	@echo "  pickle     to make pickle files"
+	@echo "  json       to make JSON files"
+	@echo "  htmlhelp   to make HTML files and a HTML help project"
+	@echo "  qthelp     to make HTML files and a qthelp project"
+	@echo "  devhelp    to make HTML files and a Devhelp project"
+	@echo "  epub       to make an epub"
+	@echo "  latex      to make LaTeX files, you can set PAPER=a4 or PAPER=letter"
+	@echo "  latexpdf   to make LaTeX files and run them through pdflatex"
+	@echo "  latexpdfja to make LaTeX files and run them through platex/dvipdfmx"
+	@echo "  text       to make text files"
+	@echo "  man        to make manual pages"
+	@echo "  texinfo    to make Texinfo files"
+	@echo "  info       to make Texinfo files and run them through makeinfo"
+	@echo "  gettext    to make PO message catalogs"
+	@echo "  changes    to make an overview of all changed/added/deprecated items"
+	@echo "  xml        to make Docutils-native XML files"
+	@echo "  pseudoxml  to make pseudoxml-XML files for display purposes"
+	@echo "  linkcheck  to check all external links for integrity"
+	@echo "  doctest    to run all doctests embedded in the documentation (if enabled)"
+
+clean:
+	rm -rf $(BUILDDIR)
+
+html:
+	$(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html
+	@echo
+	@echo "Build finished. The HTML pages are in $(BUILDDIR)/html."
+
+dirhtml:
+	$(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml
+	@echo
+	@echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml."
+
+singlehtml:
+	$(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml
+	@echo
+	@echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml."
+
+pickle:
+	$(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle
+	@echo
+	@echo "Build finished; now you can process the pickle files."
+
+json:
+	$(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json
+	@echo
+	@echo "Build finished; now you can process the JSON files."
+
+htmlhelp:
+	$(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp
+	@echo
+	@echo "Build finished; now you can run HTML Help Workshop with the" \
+	      ".hhp project file in $(BUILDDIR)/htmlhelp."
+
+qthelp:
+	$(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp
+	@echo
+	@echo "Build finished; now you can run "qcollectiongenerator" with the" \
+	      ".qhcp project file in $(BUILDDIR)/qthelp, like this:"
+	@echo "# qcollectiongenerator $(BUILDDIR)/qthelp/psutil.qhcp"
+	@echo "To view the help file:"
+	@echo "# assistant -collectionFile $(BUILDDIR)/qthelp/psutil.qhc"
+
+devhelp:
+	$(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp
+	@echo
+	@echo "Build finished."
+	@echo "To view the help file:"
+	@echo "# mkdir -p $$HOME/.local/share/devhelp/psutil"
+	@echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/psutil"
+	@echo "# devhelp"
+
+epub:
+	$(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub
+	@echo
+	@echo "Build finished. The epub file is in $(BUILDDIR)/epub."
+
+latex:
+	$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
+	@echo
+	@echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex."
+	@echo "Run \`make' in that directory to run these through (pdf)latex" \
+	      "(use \`make latexpdf' here to do that automatically)."
+
+latexpdf:
+	$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
+	@echo "Running LaTeX files through pdflatex..."
+	$(MAKE) -C $(BUILDDIR)/latex all-pdf
+	@echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex."
+
+latexpdfja:
+	$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
+	@echo "Running LaTeX files through platex and dvipdfmx..."
+	$(MAKE) -C $(BUILDDIR)/latex all-pdf-ja
+	@echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex."
+
+text:
+	$(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text
+	@echo
+	@echo "Build finished. The text files are in $(BUILDDIR)/text."
+
+man:
+	$(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man
+	@echo
+	@echo "Build finished. The manual pages are in $(BUILDDIR)/man."
+
+texinfo:
+	$(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
+	@echo
+	@echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo."
+	@echo "Run \`make' in that directory to run these through makeinfo" \
+	      "(use \`make info' here to do that automatically)."
+
+info:
+	$(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
+	@echo "Running Texinfo files through makeinfo..."
+	make -C $(BUILDDIR)/texinfo info
+	@echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo."
+
+gettext:
+	$(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale
+	@echo
+	@echo "Build finished. The message catalogs are in $(BUILDDIR)/locale."
+
+changes:
+	$(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes
+	@echo
+	@echo "The overview file is in $(BUILDDIR)/changes."
+
+linkcheck:
+	$(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck
+	@echo
+	@echo "Link check complete; look for any errors in the above output " \
+	      "or in $(BUILDDIR)/linkcheck/output.txt."
+
+doctest:
+	$(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest
+	@echo "Testing of doctests in the sources finished, look at the " \
+	      "results in $(BUILDDIR)/doctest/output.txt."
+
+xml:
+	$(SPHINXBUILD) -b xml $(ALLSPHINXOPTS) $(BUILDDIR)/xml
+	@echo
+	@echo "Build finished. The XML files are in $(BUILDDIR)/xml."
+
+pseudoxml:
+	$(SPHINXBUILD) -b pseudoxml $(ALLSPHINXOPTS) $(BUILDDIR)/pseudoxml
+	@echo
+	@echo "Build finished. The pseudo-XML files are in $(BUILDDIR)/pseudoxml."
new file mode 100644
--- /dev/null
+++ b/python/psutil/docs/README
@@ -0,0 +1,15 @@
+About
+=====
+
+This directory contains the reStructuredText (reST) sources to the psutil
+documentation.  You don't need to build them yourself, prebuilt versions are
+available at https://pythonhosted.org/psutil/.
+In case you want, you need to install sphinx first:
+
+    $ pip install sphinx
+
+Then run:
+
+    $ make html
+
+You'll then have an HTML version of the doc at _build/html/index.html.
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/python/psutil/docs/_static/copybutton.js
@@ -0,0 +1,57 @@
+$(document).ready(function() {
+    /* Add a [>>>] button on the top-right corner of code samples to hide
+     * the >>> and ... prompts and the output and thus make the code
+     * copyable. */
+    var div = $('.highlight-python .highlight,' +
+                '.highlight-python3 .highlight')
+    var pre = div.find('pre');
+
+    // get the styles from the current theme
+    pre.parent().parent().css('position', 'relative');
+    var hide_text = 'Hide the prompts and output';
+    var show_text = 'Show the prompts and output';
+    var border_width = pre.css('border-top-width');
+    var border_style = pre.css('border-top-style');
+    var border_color = pre.css('border-top-color');
+    var button_styles = {
+        'cursor':'pointer', 'position': 'absolute', 'top': '0', 'right': '0',
+        'border-color': border_color, 'border-style': border_style,
+        'border-width': border_width, 'color': border_color, 'text-size': '75%',
+        'font-family': 'monospace', 'padding-left': '0.2em', 'padding-right': '0.2em',
+        'border-radius': '0 3px 0 0'
+    }
+
+    // create and add the button to all the code blocks that contain >>>
+    div.each(function(index) {
+        var jthis = $(this);
+        if (jthis.find('.gp').length > 0) {
+            var button = $('<span class="copybutton">&gt;&gt;&gt;</span>');
+            button.css(button_styles)
+            button.attr('title', hide_text);
+            jthis.prepend(button);
+        }
+        // tracebacks (.gt) contain bare text elements that need to be
+        // wrapped in a span to work with .nextUntil() (see later)
+        jthis.find('pre:has(.gt)').contents().filter(function() {
+            return ((this.nodeType == 3) && (this.data.trim().length > 0));
+        }).wrap('<span>');
+    });
+
+    // define the behavior of the button when it's clicked
+    $('.copybutton').toggle(
+        function() {
+            var button = $(this);
+            button.parent().find('.go, .gp, .gt').hide();
+            button.next('pre').find('.gt').nextUntil('.gp, .go').css('visibility', 'hidden');
+            button.css('text-decoration', 'line-through');
+            button.attr('title', show_text);
+        },
+        function() {
+            var button = $(this);
+            button.parent().find('.go, .gp, .gt').show();
+            button.next('pre').find('.gt').nextUntil('.gp, .go').css('visibility', 'visible');
+            button.css('text-decoration', 'none');
+            button.attr('title', hide_text);
+        });
+});
+
new file mode 100644
index 0000000000000000000000000000000000000000..c9efc5844a2627a8474949724a2aefe4ab2baee4
GIT binary patch
literal 15086
zc$~#s2Ut|c79LBU7>ye2(Zq@!8-^wzy+{+#s4>rIEQzRKtg)b&*kV*bKod0vHHs2@
zuLvlhf?ae`v0<V{F`8%=fo0w~Gxx&X<?dx=l{eov?zimj%>U1vGxMKwu7p$})kwX1
z1YTQ`uc{MbNeF4#lE2>!e_soK>)u^>Z$^lFLqa;hck1Ey2>&}a$Lhq8W&-^~=pRFO
zhVB8~4Z1b-7Q*LxTb~QheQYilWOloxQMbE5Y4c1<o2D12Ojjn&gpYeeH&yz*-z|;W
z^#-N3DoVRwp%ll!)+|G#MheiIL$3+_9Y&3is>1vFIQF1iO8stA%Eq_`V_c@xOuzx3
zI|;nHK>rAOErCxf=yv$o7Y`^E$FNU-n9wWr@s>_0kGHf+e7vQ}5#CK#r%e~eYPn&G
zW9a%x_UbhgY;k<=agQmLj^P40Yyd|$z|r<R$AR5+Rmu$bey{CeF4s0sccSYi+f(nJ
z&4+~MzTAUj42LlW!Wh1iF}g~|_#pY86vVK5uDg0$m@D1%jU$cv(lP;;Fy!vvn}Q!{
z)WiQM9m5&Mu$GJ=tf$AJg?;JnxgPYlSuS+r)IKzNjOBi}9?d?3&wQYJ3j6QmcH-Vx
zr)-TH$1sO6+MH+W>7Mw5FFi2di|!0}rwKEi>4qr|bj^g`bVaZgjTvJ}mw)xKdf~91
z`{BF(Zs(pXa=uQf)m1(Q{LTJEL_d1;dmp-Qo+sTg$Bl|>u{zY2{a)<C7%twoD0PA{
zEVDFu@V;$YRN%4XrT+BDB5%6)J5MUEMcgEN`qOwDtuc_#fP0ko&C#eGvR-`)@83n6
zI~n0O`}ks?xc&1z*KG@P*#Ps$uNY^O5INd1VdXe$t=~g$qGZ3g7P};C@v~$t1e<B7
z^!uZWeVDzAYq5T^L&;hY?$))GexJ0|Z^z*Uee>8_%yy;muoi2-wo|Y8%4)gr+iKG9
zKdT{hr9mYvyoTgAH8`M_ggd5q&V<)9aImsX^krNlILSy4=(dEfo2xL54fL*r`z-pr
z3E}5}u?^?0gY$Mjcyo4-)TjHpX8fz_knt+7T}B~ok*3aVn(|UrfA9T-S_`&?!1uff
zKQr18zOKe%sOg;Xc&gLYf;@+-Mbzd>5$$!Uh<3YBNIRV^q-KDj<>^A&JiUN6N-d!E
zlJoOSmL8f#_`2X))G%gp|7`VK-y99~ysn`xsv@cn!=#)ddN042&b(Db-#<}6O_m?U
zbIbzzd&bN^@ODvN;B5`{y{QMod5%Ha*g70}ewJ_>dEc1%hvXL1Pwr}{E(UuY4C^0h
z*xZr#HMAM*MZ=_*D#GtIqvjv>dodL;1l%f%!5T1FTr6D&(H@$fVDsaBX6X8(oukjx
zh28*qW9X)%9u!ku3_gItLk2@vz|c{^@KKr?=WkE=z1&0?uYoW=+GG`-xzWekLboE^
zuic?r20tpMS{Uw>Vt~&-h3-fA`CDFh7sf@Ignl9Q&3D&Nb(oqk!&$X?x?^7aH%|0d
zxbyILp>XFaVZe287T4jj_Byo1^8xnagR}zLASFMqUgArYNz`G~J1(TuH>+(AbNzPL
zTz7W1Z-x7I%M53BSK<7V^C%TDj06my8-bzWN$`sl@XZK@0nf|#H_Y*DzIUFddhfR$
z?0(t~cLUz}c*nr!UQ?b@I!Ok@r}v8K067d<dN7<S#ZV{lg-Y0ykKkSmKeV7P-9OKZ
z?g0#_7x1pedlEkP#rZ`HA%J0w42FJsF!WTwP-Du9kubjbp+(+14}(TH2pIOk-H4ip
z?L(Lgof6nNbn+8To?Z<1wJ~@D26q_@=76Dt4u<->@1rKOPF(DJ4e$2D3%!|M!uy%o
z!fZFtOZExFPpQ5W=YJgxPS=X4oeYLHXTUcBLz857KG-EM^QXsu@MBsFHQ)aErTc)k
z@U?%ZNr++M<D%S(Vz83I&^+Z|oZkU;9_lpIi$}zL0L`}>F~B~cEv%YgoA8Bun^A;o
zPcJ1u_c)$C*Z2A>6~mCN2Sa8dZGGw$>O{NLr~rx>l9u?<V~c$$+QNYnTPW+3crL61
z4GG$b>8~HhTbJlK>`O=XIy=(6^#t$B&-N-|FiU6rEmN2G%T0|8peeWyOT>MU*aF)J
zH|~=&oam-$j!ZwIjztZ*Is`C)7L5%q)w8IrN4mG2ptKI1PW^-TW7qWPpkwLF1L?^~
z$v%j-AoWQ+7r-a+T-Z3R57VE&OtfQ~epQGKT{+fTOH)UVworK-zc$w&?4j=s4RzDO
zV4m`5GtA%SbnJkL(=kC5^g7=M#IRV$76hLZ&xLq#A0Qt11@>VL>;r206=SW+==%O(
zlTr+hfT1^FFyDFcYxulT`szWA&qN2RPelh&w1t#qqAkeyq^>PY5pAJ2w*|HjR$B89
z2ESk!a!N5cWEEhH)k(O6NM`ha*=J(=Q@#(nw!nQ-?tI>;V+(8_5QAj?q2Qak7@W>O
zk0o4}lxY6U6+vUuqXTo(5JQBvEgY1d&(eJ;V+*!))p)dplDNim#2>{}#1MF^Q0;q7
zy&nEvo9M(F3e8lwvt|8VY73%IGFyOsAO^%`<u$esGPZy|$!$T$CndJ<Cg#U|P&%J~
zo9R;OlZXNKL9_+JV|1hD7tiMhmya@id*{rKGUqe*Nv@enY$258Jsb(wd=+l&d<LJC
zHr$8u&gV6uz0t=||0>4C<<2jh&v(<~+1y$CB4o~I*D~ib*x*LO<4{BGT(+H#^mj>%
z?58esKI>{G$@v^N+5R};X+Fa;d*w7dBTq&KM!@_T$Cvo3bkAp)U%hR%iwgAf@lDhE
zV2%iNZB;|Yrr`t=K6B)H66o`A_)d5QFyn9V_xi?$PHA`*ig}9e(1#I8p2DmG6Y6gm
zV_;4a<1mbYFfV|43Ov&=KD8%2pNhFuC*eK*9b@OtgvSY(_b8L2sf32uG4FygoJE(d
z7bbO0ez>Je>R&0HGhSx5OMjVdmhmc&Y06af{iY{gWH(NJkzN15qy2TZ=B%x`aC<1>
zn$3}L&UhBRsl1Fq*liM3E_UbtNw&LEptiljwFkx~-7geU^K(2lXqU+~shCG;3i`Ye
z#0aJ*3TWM={5+Gb_kOE7Y!=3v4#a?5_Zw=}oiiWzb5|9rG0sNag7IC2I6%x-D=|N>
z`rM5Z1rBJ3Z`GE(uRXKyxlyP_y&>ibL=KoYvDCw%^%)+oA_td?5HqD~bErCe_F%&O
zqUPJgADHuMC&n_qf@ad<kfp#OgL6oKUd--`=Y^CG1<s5^GQ{3na@G<adsjRgYC!ws
zcA={OZ61#q%At$EVa$ypt@}0=xHJ@Osm{?C*@T}{M&0Y>HH;?*-qlcD4(<vZx(OVH
zW^3a=n5Usl#QaCni~EG@qQ-9%|9^#;Sc?P1VqW?<T;g$=$U)2}=H?euFZc}oLF7Pq
z3~ZFHE3aX$%UBLlf55zl$e}XukNkt@>qHKiyA0C9p^p%k%5mr*<TIrl2+vU})+-HY
zc>dy@jv5hdv5BOce)+JNmT<`B@za~)K=}FDLT66wjR=nm@qSa%Z~qa#YYx2+;r`?$
z=~kF4G?W8;A2nk?oiQrXF~^HJ_x1u0IsN-iOmOecpwZ(&ujXOgfN?D9b}@dzvBnGe
z&e6bOgdPt5Lf(<>Lw4DH_*mSB^JVt|b8uKEXp+i(8fzxC;cPWocR8AH&D4`{8<XDC
zRo8~Nnr#nr&1Latm<!YV7=vOQj4>d_9*BR!6H1NcV6DKRl^zat;Et=g?+MnR{RKOd
z#$P78!rfFDKV$5OaTCUF2}0b0@!Lk8clW})H{<Z90*5>D95Dad=c+u1&gXdkPcMfQ
z&cS5U^<N0j(>E3OU}v~%D8`+8gj|f6lfu{!Y>9K2=BSl7*T>;A1rBZs9J(rSXbc=0
z2prx^%2(@XrK<bpd8sgF+$-d{F>b^>GvhFm$IuwZi};l|e6GO3^9^yRy@B}x#zXb@
z%=2!>;%*`C#eCRqIXjxc@OuMpwO$Sn6gcE4aJa0%;dEIJbrYG^=nMU$gY!MdW6X>>
z9G1VBC)kk;hakHagD3u3q|(j%BZqN+^1Qno2h6_*>fwMj)82YGw9n+V2{{h$PG2<w
z@OM1?z0W$#L5a1J{Xz~#&KDMb-fL0t&8I&}@t4$*Dw#vw_$++Bp=aV^9~I{JF?WKw
zJTa#!=L?&rIibewH!)9>YcPlV3LLKM=g{MVeh#co1hF(=u|2lLFBkKGn3vYIBROAK
zI?5`h@0$2whH${z<`)VaycIa~QsD3*t2429!47lUm{-UAm1swp!#W_fBO#x+O~S!$
z=7Pb&*B`Ie<?%Wk{EXnx?8HlkU(ADIJ{a>~N2PWo<N|lg_yTB(?D^miFh&63&xX8?
zp7F4W+cntd($jcfh@~sSp~Xp#A9I+PM-@4UzMyrcN_;^{Utq2s^UPTHz&tPJnlayv
z^_N&l{UvI2ulo_Bd!3yU)Nx_Qsf#}GQRQcf99)HZkQ@hd;aLXc&^nFbw@Hn_9H>yA
z5pv>kzM$_+mFf$|VUj(|Q?nXcD6d;E4#C<rB(X0WWpU2EXY(O_vtA~Z&!Mn{gBi!)
zBP}XGg}H33tyIJpN;pV#D%KmY{v~q2y2nbL8kDpz8POxfeAcr5Qd`pHV5P&sEb-wM
zJpa?90(M}1irG;GeL+rZ#|gF6HDWDuyfv#IN$Z)?KHjJOOz#U%f0X*P$U&MP6FHde
zyAc8STb+&x2*Vm5))`O!AACW&2e!ZN8;H+M7{b9U?!=dXzj1n`Z&$37rbh<?hX7Wu
zWp=bwu%k-yg^1A>XwUBbg=arR4jzm{kroHbi>%Ixd2W2Rhn$HH%4HnTj)b~<vWzd3
zr!S;hyCS}TXX_x$X-GJT`7tR6tBmK#gg=wSo}tT(2@1nHEwdvTUocc(NVPWBaIuc8
z?F)h(>G1``kIw*=$HC%Ic8Cx|mc;TIu>+2si4izNiS=gXGgV1z>-qw-BN<=N#g8>%
zB@WJ6?D??|2(O)JwKFk6$6m`9$~#kqy5V{mUl8qRg?3%vYxwWHu3eHJlW_1-73TIn
zb_3(C|H$MYSW8_VH273>U?$e~jPV6S&Q!)>Y^g6Getd36mqXyKBDMeZSG(L!J;0ii
zv9&|AJIs?Aq;>TAg3OspDj|RPHhrNo@K;!07~l()f&Xpk3*=B4_@(+H^~VwPZpKdf
z`=ui^DR!9A`hrwK{X%-Cs-Hb7sipk;?4i;6g7BPi{kMug!e1?FZQYg}JG{dBVs(g3
zF5$V^+HVs-=<REwzWD3j<r3_FKgucJ7Zmgb_%CW2{C`|!?$tMnKQb^v)EDWoL+H)p
zYv}E?c$yqFsKQzs{6M{6s0HTu@&D(%)n^FsnHPNa=S^wtUne`LV}h;l8CJ}P8}w|<
z8{rTY5Qn~CjMj$rSN$AfhcyY*GnMh|Mwynf#CI@g)VQQ2zL|+X_^1HCT25>43U|xh
zKF3uB_OmN~hU4;$-`L@EG}Vp8O^e{rqGS%uC!{XEJ}Z5#K}i+imAvjN`~OunNR>PI
zT8%yPgh=OvOJ8C5aAUw5(ZY3Jlkgu{$vgO3tpxvT^HzGTi?6WGE!aa^{9&#C0an3Y
A-~a#s
new file mode 100644
index 0000000000000000000000000000000000000000..7d975ec9d2415c3edea7cf9d73db1d9078358daa
GIT binary patch
literal 4922
zc$@(`6UFR_P)<h;3K|Lk000e1NJLTq001`t001`#1^@s6sN2#;00004b3#c}2nYxW
zd<bNS000v4Nkl<ZXo1C=$&VySR>ps3=I*g?xo2foc6L`)?=5Dar>6%Ym}Za|=72bG
z;53~1AGjcK<AV4rkmdl0!@vb3-~xzQTD{G5S9k4|Rhb!)8LKa5_Bi;Gky%xp)ze70
zWb#PQ2zUSNd+&SinLQ;ULUD))N-35u{l6U|g4P-U?|pSXJUp!4QAF6>+(an_P=3F9
zdA)qI^8B>ny?^Ha{;!Ak9;Fm%nsR)6jQ1X`HPh*oIF4CcTVri)jW~{(&*#-7jK|}1
z6QoM!${Tp^$+C<jNmwiv=Vr2;v2v!q5);4^zY+nZKm<_=RlJ8W2Im};$)sW=iXy!C
zL{UVy+eJi}PN!s9Mzh((d(V76r`2l7>gp<5>oagAbKZNV(<zh5gl4lznx<&25nsH3
z5|I3X9zo^5Mo_5Y1)rFJi`PpqOOvHUstIu3b8v7#x7%fHZH>djLqvpbw@ahZsLa$D
z!*n`jKA#gs5$$%H)6-K4f`E;U4T6hisg%N6%VM!$u(CpCElL|qpwQX?f>s*q9Dz}2
zrO9!q>ONZQbAF+<#*3gz_6sI;0h9u$_nt5aI316%*3#*8I6Xb3-|rIy0dX92|Ni~T
zMT{{F1_OG%9@bh;Pfr0jJUnD|b@dEfIn(8=IOj-`ggA}~!-(N%$mz+5dcDE%@sKy)
ze1pk&jPst^Y=+jFZnsOVR^##G$F$pR;y7k&Yl|dFXt&$vm{Ur@Mdk`WtJUlDdOhyn
zzt8&mI&mD6Bnk8RoG=VA##9q`aBx7g*`!vhVXb8}8nM5>PZ)-0;Fj4dA83q0X-yP{
z%x5$1-nq;A#yTr21KRC2_wL=}_U+rOt*zmlqt$BRti^lJa5%(T%g)XYQuvX0kJ387
ze=(u51k4oAj-m(?1SCm<b&mOLhI5X3y^hwJIF11bf`Bj#E8i>q&KOfp*!fW4oMSW^
zaeREt*7kPAic%V50w5Qja^|8a!aI)_PZ);GW-~;DPN&1kXhf^kBn%_0wJ5Ei&=8b9
zCnyRKrLfN7tmW~eM>ywbx7$o66QU@hR;w|YOvthftu<O}n$0FzmQ|pVB$4gyZLVCo
z@^qgoO*EGQRe%9&GmOzBNrH2ZMx(*;@iDDd3u6qU(TGN)L1+v~n$m2waU#sd6I#s{
z-U}#=@`6%Q2~fqRQrx?9C!YwVsMqVnag0(5=Nu=er}TS0u3Wi-00##LjD|y$Qp9mg
ztyZJk?J^#ZnM@|<eXe9<8D#Dns+{1;u|N9gBUV;cI5|0?*=P{eYQ%AjF@~L;t5}<I
zGCTtBna!qbZ*H))y^XUT69k0-8ALRmJm885qtS?3twt0@WLbtW1^{a<S(>u5vqO@m
zAi~w%U2fmHRgqDv)he+`lH|P4EelIQ-8s1~<6ymB=f;g20Bmh;7AB_&gODUypnc5a
zqZ2;4KVh`6%u~nw)4N2CV?yoe)B;*jK))66>XklM)>j~`VFH7-7Oiz98s#&swRq?7
z&Jh&qTY}J9)9dvJf`Bwlan6yZ>674|1ga_@TNazO_4Ql`L@-8UJ@_={i$_EL?)@Qm
zPb{$o@rKk2ne(LSDY^&*+IvC+_24eQbG^?W|K@ep)>c_tTVp<-kt7Mm7;3c|S(X71
zMiCDW4%ph>Mu~9y_HF9*dajH?fQVGW(r7fE6cq1$B`8;Rb}C0*1{?$dS(a6@?gb(P
zKmY6jfAjATIZYJJP=k2Jixh)^_#BpZcrQ5ban>W^h*Qh=UmNgeKln8UD+81$Zr{Ge
z!NCE&UJtEx#gKE3D2h;8<DDZ6!^(WU_ne-d%8eU0xO(;KS#J4M=E_kxG*E%p#uRF&
z38Rpc(+Th28}ncazrNexum9vV{^Ad>v(*mp;_)I_>#)w}_i_$}Lm{+lh97@$$p8HE
z0opslTEyDwYQ;p!++;FgGMO-&%_?BV7&@H}K@i}IYpbiPISH4Ur5B+QMSSqV2h8Vl
z`hx){!y)gz_Z}a7_#sC}N9<g=!e=+X;Aq?;O*4LDuh0H^hev_pn|odU@%=}H>dB<s
z`!Y$+GnS9;4f*YFWHiHE884byuh&B<MHq%vC<ua}^3l?wPESv1Hk)4#4y7vk*VopV
z&SrGlZT5C|vCh#i9#*T@xq9^~|2-N~3pD@v#R=Cp8jR-|Ke?6rnRv-_O79UlKRo&W
zj>ikU7m_&U;ll&k?KUVyR4}xhodD;=rcB4eFy!IGhv#$4ryU}KDFW-&y*+{;|9X~X
zSm)T;-DOv4l-7A^^8Sc=p!wOI6YdS?IOjMxjWH_sv5GbS^fE^)T_gZ)u3dYHJ9qBT
zXw)l)7mGzD_hqQEMMhKt6%qD|cfHgsMJcpWRi1hG?p?OFwmBV-i5D~0*VY&fM<}hy
z(iG<%k%Idt3zT?54bDl<k}uAMNlNiD9*;s8PsW^{j!9EXl4SIHeI7kJ;QF-}(I&(>
z$MNwojYgvi18JJFzrRlq1l+%WpBG+ufwi?YMC1~1MOp+@iuvHd16&$&G#qj8_?Y#L
z4Ti%Z+89>nhx}HUVYKGj>o4IfSm%hM1`lrilAn$0+)M_9lHffRIKd+bi}`|I{PH6f
zv%D(kc6+qiT^5OO`1lsa7}7MOUaun}jK^a{gfva*cDuas#v4^gxKvQenoBE%Ac(+s
zzWoj#-8$ftx#x?t!Re<d-ml=rgKt5Y=b4{;njwWRc{d}CSD08ZV)1!QSgN|gSx2wG
z%FBC}o$lv2Cn#+=nJ6AUx<wehNfZSrrLoom&}cMB)3h?jvLY`NkuPU1|0bdo;=v{h
z{`LJY_|XS5hOxrrQUKoPKIMJ>AfLxIFS)PbJt859193~fRsa-1k$=~wC$wtEh-eg^
zPF=XVdY^lffGqkR+gmFnX&xGy%_cW*-lWxPQLopZc>gbtb459#B!AgY?;r8EKOZx-
zhGrlb<<a6%lAkpmgJ5uIC1~*&^6Oe$#g-HkQTd?v7^8Xk;33DyLqr9I*$U2jyoa^m
zKX`ceztAQk2uvmYm6e_4BGqwuC{Q3MTpIIlpPjIf5G{_>c_^7#id(V-z*n)X3<GB(
zQZlEi<qe_R?a*k%D6x5f7mpST2(=((f9)Q#c|xP6@S-?N?$5^aGglOmq7>8Fj86_T
zvdk6LdQm}C=H)9z^o1|U((o=f+2tYL<Eq?LxN&uptyK`0qQrsNd^m@alx}c~=`1Fy
zMTBAWRJNWQTwW!E!E<*wXOh^W^tt%*Qu$hWT|sV|)!=LZ1~6JvGXd5K^}rFv$F$7-
z+%J6&OqHK;Xg_3j@;T%2j3mjc@h<~-d7LBnyMu8?l6f>N0XvIdl&KWCnWom_oX7i|
zX}=ujT+T8|A>Prb1-!f4=dI0~v};FsW$qo|kiu8<YcsO>O%{t6>2}OhP4T(Goh`w6
zW~s&cJRF?)&Dq&W4lK2TB4f1`66I@$g;e|E9ep)%MnM!tyuH`p_g|m$`t}Kd&cG>@
zWFQ_THc!yKB`~l)2pO!d5eC_lONd{UxzgcN>kIKvMWJ}!$CL<}6V~dUZ(ZqfwV$xJ
zE<~Y5ye`(b1%*OsNYji)q}l4mw4?hB8Xpppg3~C{LTqfVu->DTM>&hNBWClMZVQ4i
z{2FGtv;<cVG+I1XRPjKm%nax7N-@w2es5#UAH91(zdfWLd33Q3l$Z6n03jY{Q;Y`9
zgeX{m4-ru)NeiEKRa{i!KnXTWm}eOsqj1g=gkQtwqyVOrrrQWG2&perv|tVqoCpmq
z{P3MMzO#S8?&br6z(6jl)e09lz=L-X<dXs*t_I`^DJ2;3xv)@tb{3SO(cUBq1C*Ap
zXO<|1K@erw>DLJjOj1Xv%Gh-#5-$!KytO-Lf9Db2)$!KnOYbQ1h+F`b;zJ&#QQ|6=
zL<+|I5^FfTfFePuE)u;&6oN=_>7K=<agJj7dv~=%udWg2s;r_^O+;9YVkV;x5x_f#
z)_KmDSKAgP8H!>^mS3ZYV?H0s+ngae8{#d>JH%xqeg)ll0m$>y%b2@7&K0B4YVpQq
z1I1YdUDjpR3H^p<ce{h~ptZ^g@`VX{2a@F=Dll0-#OD92&c(o<4M`C3jO5$28qxWR
zVrl$J%qgV^qZ+^a#unWgI4^{T+!t^d<!QBBL}5g(h;o);cv}QyhxZm|&*I)$){>`R
zUL?Qf1n*q_T?a}z64^q!@6o7foIAf?_^fz$DRW4^I*ii1vcJs_-`%019Vhb)D+()$
zdE%JO=7k#OD_W(g<yl4s&Z3pYgeh9h(ag|#j%JQ#nh%+xgEYUc6HJ(4!UeNf^U=u<
zP^QOZd`cY0q-jzCdlq}oRjev0VqRF|`|rHMR=>&5?~M4#$6qj8EZE+=f}cOeS7xUQ
zbIP*}=LHj_+&^e=`=HJ4b{`Xj%%)>%VZPa7v_|0=4G-ycI>hOm;b=m$_ae8CuF%<h
zi%sKsd^lojdmC$QRkS`UalSMZoP`65#h@ndzIBanz3zGN&8sK{{eGYE_ynE)L%~!D
zu8?ytAPJdl<LfUob&w@+c-)}h>k)+tjVEaCQGe+*h-!o`V|B-)O^vs%)yUEbN*mTU
zHpnuI*2R8?Iy*0K1zgVD(rk!S8|vtw2HNw&-qmV}&1lFT`P|2(OrHeA5r~6SvA^;K
z`zxOo0wXXO=aWDSWWuBLd-&$tv|4SP%kPsX&4R0St9LRcf2U!w39`KOzRcd`W|^ZZ
z01816aQOH!pMLfk`}_MG92`)q)zBJxeg;j8cn$ca%G*@|I!~n>_>@Gy0b&WVo0y>3
zzDiQEC|~b)E{};K;G8AP@+G`53>c5c%w{vTx3{U)YG>BA6do=&OP*96AveWlvq`Jj
zL>q%b2&~EDl4wNIA}>7)$hi*+xRf|}g~i&R<B4b<{S}SupAZ#dy(NwlthJ<RTJ5N6
zt*O;&1VO-Xc+6t4U}tBCe!ou?Mb&;rX<e5y$6501i-jWR9NXL5?Ck8|y=Q%W9f0{F
zVRB~!#ZU1P<`uN$aV{@|%0w8HB&7N^nypo=YLJe<K{Ndkv0o>REyu_AI6OQ?n}BYo
zU2R8;2$RW##bUwM))s@ops*T!&gY&BTqUuk?=7ui8e@vBVMiEhPR0p-u}eF1w3;AJ
zpa6yB#U|br`6x7#e`fsX6-0&f7JpCdu8^3Qna@*ZvnlVq^G>zt;+$hTopN}1$aFeo
zV`GDrl@(g87C{i4+h%)iaB2w@7iJ}jA`TA^xpnIn-~H})`TXYRSU({4@9`@CLL*Fo
zEdQ;iSdPf6b1;PJh?U7-B516I+u5HI^j^aqKLi!z`|Q>-o=g}Hhn$?8Fr7}T2Ag)f
zO&EsNdwykb%hFnX)*4N|)4995%l`g8tyYV-zx8bp&v^PKkB{G`75|u)`UQqD+Rrd#
zDCH1QI0^7{u~KJjuXCjTfZE_S!oZVdj#jgkuPzUVOs7-E<1y3el)+%Y`uchWtepI3
zH2^(#C@B9<l7uMA7iSucM%C?;Gpy-#>$F;LGoE~d$CG;m*)K5m4$2SFKE+9d(|uyD
zk_OiZyBn<5^UP*8Pf0S%?$uQ$lL^!5l+)8w#^W))UXRVqO*)-UB_Ll0?76^|EfPQZ
z=})Oe5tGRTtu<j7(rUHX+uN%)C(6cvFfgnRfWbAayFq3Zne|xbG2#i8r>R_CaeGIa
zIkF7mBn5<4tHo$EItOfPYpW8LWkp;L;unu6z%A!!<!m_b^NyUNV<*cpoOASgy>rZ!
z0Q27lC<TFWL;*mVBn!^v=4YM4d7Z~U@g(trLBCHN$DEv;Fqur~_xn#U_PqUP&urCL
zZf&yG^1|L;{(r5{HK>)@dHLHCV41EdWhk1GaNZ)~@#6AsF;yhx<oz#MmN6I%7>!0u
zCKCpO0UH||bUK}Lj9s?s^#r)`#hzA1lzkqMw`$Dia}Ev;7z_rC$K$+n$T?=S8Lz(j
zDx=Ye@pz0ehQ(sR_3PKGOs3!O<6NE_7IiL4>8b;1KA$t2%~)SwKPMg+P4RiyJJ)Zy
zoL!gQMCD)!sP~?aKmNFCwz+-#Hq+^}YG-V<T5NA`v$3&(h*X<~olb`&NvhpY=Unx<
z+_0a`W^8P1u(7d0yWKt~9$y6*T<EtfkKu60a5&`UmtW3Xk&3-JMV>sD+eS~@S-E(e
zoSe|<bgKQmi<9P@!&=MH(GkbT$E>ffv$C?1?`aqN-6g1H629c90`e36mgT12a5$vX
z=~QB|eA8v0yeP-Z=0h<V%f;ly;<6m$@t9__S*28E9IIaR`5Ai>Tqy))_f6SQ`ZRD~
z<+xa5J?)w?hIYGMwHB6U_$xm5+02zdm*xFw4|!Um`m|%&oGyaCXbHxcrBEWjD!?bf
sE#Gk2M87Np_&UeM`#!6p{yNP4FWEDLi6}qb0ssI207*qoM6N<$g7`0)=l}o!
new file mode 100644
--- /dev/null
+++ b/python/psutil/docs/_static/sidebar.js
@@ -0,0 +1,161 @@
+/*
+ * sidebar.js
+ * ~~~~~~~~~~
+ *
+ * This script makes the Sphinx sidebar collapsible.
+ *
+ * .sphinxsidebar contains .sphinxsidebarwrapper.  This script adds in
+ * .sphixsidebar, after .sphinxsidebarwrapper, the #sidebarbutton used to
+ * collapse and expand the sidebar.
+ *
+ * When the sidebar is collapsed the .sphinxsidebarwrapper is hidden and the
+ * width of the sidebar and the margin-left of the document are decreased.
+ * When the sidebar is expanded the opposite happens.  This script saves a
+ * per-browser/per-session cookie used to remember the position of the sidebar
+ * among the pages.  Once the browser is closed the cookie is deleted and the
+ * position reset to the default (expanded).
+ *
+ * :copyright: Copyright 2007-2011 by the Sphinx team, see AUTHORS.
+ * :license: BSD, see LICENSE for details.
+ *
+ */
+
+$(function() {
+  // global elements used by the functions.
+  // the 'sidebarbutton' element is defined as global after its
+  // creation, in the add_sidebar_button function
+  var bodywrapper = $('.bodywrapper');
+  var sidebar = $('.sphinxsidebar');
+  var sidebarwrapper = $('.sphinxsidebarwrapper');
+
+  // original margin-left of the bodywrapper and width of the sidebar
+  // with the sidebar expanded
+  var bw_margin_expanded = bodywrapper.css('margin-left');
+  var ssb_width_expanded = sidebar.width();
+
+  // margin-left of the bodywrapper and width of the sidebar
+  // with the sidebar collapsed
+  var bw_margin_collapsed = '.8em';
+  var ssb_width_collapsed = '.8em';
+
+  // colors used by the current theme
+  var dark_color = '#AAAAAA';
+  var light_color = '#CCCCCC';
+
+  function sidebar_is_collapsed() {
+    return sidebarwrapper.is(':not(:visible)');
+  }
+
+  function toggle_sidebar() {
+    if (sidebar_is_collapsed())
+      expand_sidebar();
+    else
+      collapse_sidebar();
+  }
+
+  function collapse_sidebar() {
+    sidebarwrapper.hide();
+    sidebar.css('width', ssb_width_collapsed);
+    bodywrapper.css('margin-left', bw_margin_collapsed);
+    sidebarbutton.css({
+        'margin-left': '0',
+        //'height': bodywrapper.height(),
+        'height': sidebar.height(),
+        'border-radius': '5px'
+    });
+    sidebarbutton.find('span').text('»');
+    sidebarbutton.attr('title', _('Expand sidebar'));
+    document.cookie = 'sidebar=collapsed';
+  }
+
+  function expand_sidebar() {
+    bodywrapper.css('margin-left', bw_margin_expanded);
+    sidebar.css('width', ssb_width_expanded);
+    sidebarwrapper.show();
+    sidebarbutton.css({
+        'margin-left': ssb_width_expanded-12,
+        //'height': bodywrapper.height(),
+        'height': sidebar.height(),
+        'border-radius': '0 5px 5px 0'
+    });
+    sidebarbutton.find('span').text('«');
+    sidebarbutton.attr('title', _('Collapse sidebar'));
+    //sidebarwrapper.css({'padding-top':
+    //  Math.max(window.pageYOffset - sidebarwrapper.offset().top, 10)});
+    document.cookie = 'sidebar=expanded';
+  }
+
+  function add_sidebar_button() {
+    sidebarwrapper.css({
+        'float': 'left',
+        'margin-right': '0',
+        'width': ssb_width_expanded - 28
+    });
+    // create the button
+    sidebar.append(
+      '<div id="sidebarbutton"><span>&laquo;</span></div>'
+    );
+    var sidebarbutton = $('#sidebarbutton');
+    // find the height of the viewport to center the '<<' in the page
+    var viewport_height;
+    if (window.innerHeight)
+ 	  viewport_height = window.innerHeight;
+    else
+	  viewport_height = $(window).height();
+    var sidebar_offset = sidebar.offset().top;
+
+    var sidebar_height = sidebar.height();
+    //var sidebar_height = Math.max(bodywrapper.height(), sidebar.height());
+    sidebarbutton.find('span').css({
+        'display': 'block',
+        'margin-top': sidebar_height/2 - 10
+        //'margin-top': (viewport_height - sidebar.position().top - 20) / 2
+        //'position': 'fixed',
+        //'top': Math.min(viewport_height/2, sidebar_height/2 + sidebar_offset) - 10
+    });
+
+    sidebarbutton.click(toggle_sidebar);
+    sidebarbutton.attr('title', _('Collapse sidebar'));
+    sidebarbutton.css({
+        'border-radius': '0 5px 5px 0',
+        'color': '#444444',
+        'background-color': '#CCCCCC',
+        'font-size': '1.2em',
+        'cursor': 'pointer',
+        'height': sidebar_height,
+        'padding-top': '1px',
+        'padding-left': '1px',
+        'margin-left': ssb_width_expanded - 12
+    });
+
+    sidebarbutton.hover(
+      function () {
+          $(this).css('background-color', dark_color);
+      },
+      function () {
+          $(this).css('background-color', light_color);
+      }
+    );
+  }
+
+  function set_position_from_cookie() {
+    if (!document.cookie)
+      return;
+    var items = document.cookie.split(';');
+    for(var k=0; k<items.length; k++) {
+      var key_val = items[k].split('=');
+      var key = key_val[0];
+      if (key == 'sidebar') {
+        var value = key_val[1];
+        if ((value == 'collapsed') && (!sidebar_is_collapsed()))
+          collapse_sidebar();
+        else if ((value == 'expanded') && (sidebar_is_collapsed()))
+          expand_sidebar();
+      }
+    }
+  }
+
+  add_sidebar_button();
+  var sidebarbutton = $('#sidebarbutton');
+  set_position_from_cookie();
+});
new file mode 100644
--- /dev/null
+++ b/python/psutil/docs/_template/globaltoc.html
@@ -0,0 +1,12 @@
+{#
+    basic/globaltoc.html
+    ~~~~~~~~~~~~~~~~~~~~
+
+    Sphinx sidebar template: global table of contents.
+
+    :copyright: Copyright 2007-2011 by the Sphinx team, see AUTHORS.
+    :license: BSD, see LICENSE for details.
+#}
+<h3>{{ _('Manual') }}</h3>
+{{ toctree() }}
+<a href="{{ pathto(master_doc) }}">Back to Welcome</a>
new file mode 100644
--- /dev/null
+++ b/python/psutil/docs/_template/indexcontent.html
@@ -0,0 +1,4 @@
+{% extends "defindex.html" %}
+{% block tables %}
+
+{% endblock %}
new file mode 100644
--- /dev/null
+++ b/python/psutil/docs/_template/indexsidebar.html
@@ -0,0 +1,8 @@
+<h3>Useful links</h3>
+<ul>
+  <li><a href="https://github.com/giampaolo/psutil">Github project</a></li>
+  <li><a href="http://grodola.blogspot.com/search/label/psutil">Blog</a></li>
+  <li><a href="https://pypi.python.org/pypi?:action=display&name=psutil#downloads">Download</a></li>
+  <li><a href="https://github.com/giampaolo/psutil/issues">Issues</a></li>
+  <li><a href="http://groups.google.com/group/psutil/topics">Forum</a></li>
+</ul>
new file mode 100644
--- /dev/null
+++ b/python/psutil/docs/_template/page.html
@@ -0,0 +1,66 @@
+{% extends "!page.html" %}
+{% block extrahead %}
+{{ super() }}
+{% if not embedded %}<script type="text/javascript" src="{{ pathto('_static/copybutton.js', 1) }}"></script>{% endif %}
+<script type="text/javascript">
+
+  // Store editor pop-up help state in localStorage
+  // so it does not re-pop-up itself between page loads.
+  // Do not even to pretend to support IE gracefully.
+  (function($) {
+
+    $(document).ready(function() {
+        var box = $("#editor-trap");
+        var klass = "toggled";
+        var storageKey = "toggled";
+
+        function toggle() {
+            box.toggleClass(klass);
+            // Store the toggle status in local storage as "has value string" or null
+            window.localStorage.setItem(storageKey, box.hasClass(klass) ? "toggled" : "not-toggled");
+        }
+
+        box.click(toggle);
+
+        // Check the persistent state of the editor pop-up
+        // Note that localStorage does not necessarily support boolean values (ugh!)
+        // http://stackoverflow.com/questions/3263161/cannot-set-boolean-values-in-localstorage
+        var v = window.localStorage.getItem(storageKey);
+        if(v == "toggled" || !v) {
+          box.addClass(klass);
+        }
+
+    });
+
+  })(jQuery);
+</script>
+<script type="text/javascript">
+
+  var _gaq = _gaq || [];
+  _gaq.push(['_setAccount', 'UA-2097050-4']);
+  _gaq.push(['_trackPageview']);
+
+  (function() {
+    var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
+    ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
+    var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
+  })();
+
+</script>
+{% endblock %}
+
+{% block rootrellink %}
+    <li><a href="https://github.com/giampaolo/psutil/"><img src="{{ pathto('_static/logo.png', 1) }}" style="height: 30px; vertical-align: middle; padding-right: 1em;" /> Project Homepage</a>{{ reldelim1 }}</li>
+	<li><a href="{{ pathto('index') }}">{{ shorttitle }}</a>{{ reldelim1 }}</li>
+{% endblock %}
+
+
+{% block footer %}
+<div class="footer">
+    &copy; Copyright {{ copyright|e }}.
+    <br />
+    Last updated on {{ last_updated|e }}.
+    <br />
+    Created using <a href="http://sphinx.pocoo.org/">Sphinx</a> {{ sphinx_version|e }}.
+</div>
+{% endblock %}
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/python/psutil/docs/_themes/pydoctheme/static/pydoctheme.css
@@ -0,0 +1,187 @@
+@import url("default.css");
+
+body {
+    background-color: white;
+    margin-left: 1em;
+    margin-right: 1em;
+}
+
+div.related {
+    margin-bottom: 1.2em;
+    padding: 0.5em 0;
+    border-top: 1px solid #ccc;
+    margin-top: 0.5em;
+}
+
+div.related a:hover {
+    color: #0095C4;
+}
+
+div.related:first-child {
+    border-top: 0;
+    padding-top: 0;
+    border-bottom: 1px solid #ccc;
+}
+
+div.sphinxsidebar {
+    background-color: #eeeeee;
+    border-radius: 5px;
+    line-height: 130%;
+    font-size: smaller;
+}
+
+div.sphinxsidebar h3, div.sphinxsidebar h4 {
+    margin-top: 1.5em;
+}
+
+div.sphinxsidebarwrapper > h3:first-child {
+    margin-top: 0.2em;
+}
+
+div.sphinxsidebarwrapper > ul > li > ul > li {
+    margin-bottom: 0.4em;
+}
+
+div.sphinxsidebar a:hover {
+    color: #0095C4;
+}
+
+div.sphinxsidebar input {
+    font-family: 'Lucida Grande','Lucida Sans','DejaVu Sans',Arial,sans-serif;
+    border: 1px solid #999999;
+    font-size: smaller;
+    border-radius: 3px;
+}
+
+div.sphinxsidebar input[type=text] {
+    max-width: 150px;
+}
+
+div.body {
+    padding: 0 0 0 1.2em;
+}
+
+div.body p {
+    line-height: 140%;
+}
+
+div.body h1, div.body h2, div.body h3, div.body h4, div.body h5, div.body h6 {
+    margin: 0;
+    border: 0;
+    padding: 0.3em 0;
+}
+
+div.body hr {
+    border: 0;
+    background-color: #ccc;
+    height: 1px;
+}
+
+div.body pre {
+    border-radius: 3px;
+    border: 1px solid #ac9;
+}
+
+div.body div.admonition, div.body div.impl-detail {
+    border-radius: 3px;
+}
+
+div.body div.impl-detail > p {
+    margin: 0;
+}
+
+div.body div.seealso {
+    border: 1px solid #dddd66;
+}
+
+div.body a {
+    color: #00608f;
+}
+
+div.body a:visited {
+    color: #30306f;
+}
+
+div.body a:hover {
+    color: #00B0E4;
+}
+
+tt, pre {
+    font-family: monospace, sans-serif;
+    font-size: 96.5%;
+}
+
+div.body tt {
+    border-radius: 3px;
+}
+
+div.body tt.descname {
+    font-size: 120%;
+}
+
+div.body tt.xref, div.body a tt {
+    font-weight: normal;
+}
+
+p.deprecated {
+    border-radius: 3px;
+}
+
+table.docutils {
+    border: 1px solid #ddd;
+    min-width: 20%;
+    border-radius: 3px;
+    margin-top: 10px;
+    margin-bottom: 10px;
+}
+
+table.docutils td, table.docutils th {
+    border: 1px solid #ddd !important;
+    border-radius: 3px;
+}
+
+table p, table li {
+    text-align: left !important;
+}
+
+table.docutils th {
+    background-color: #eee;
+    padding: 0.3em 0.5em;
+}
+
+table.docutils td {
+    background-color: white;
+    padding: 0.3em 0.5em;
+}
+
+table.footnote, table.footnote td {
+    border: 0 !important;
+}
+
+div.footer {
+    line-height: 150%;
+    margin-top: -2em;
+    text-align: right;
+    width: auto;
+    margin-right: 10px;
+}
+
+div.footer a:hover {
+    color: #0095C4;
+}
+
+div.body h1,
+div.body h2,
+div.body h3 {
+    background-color: #EAEAEA;
+    border-bottom: 1px solid #CCC;
+    padding-top: 2px;
+    padding-bottom: 2px;
+    padding-left: 5px;
+    margin-top: 5px;
+    margin-bottom: 5px;
+}
+
+div.body h2 {
+    padding-left:10px;
+}
new file mode 100644
--- /dev/null
+++ b/python/psutil/docs/_themes/pydoctheme/theme.conf
@@ -0,0 +1,23 @@
+[theme]
+inherit = default
+stylesheet = pydoctheme.css
+pygments_style = sphinx
+
+[options]
+bodyfont = 'Lucida Grande', 'Lucida Sans', 'DejaVu Sans', Arial, sans-serif
+headfont = 'Lucida Grande', 'Lucida Sans', 'DejaVu Sans', Arial, sans-serif
+footerbgcolor = white
+footertextcolor = #555555
+relbarbgcolor = white
+relbartextcolor = #666666
+relbarlinkcolor = #444444
+sidebarbgcolor = white
+sidebartextcolor = #444444
+sidebarlinkcolor = #444444
+bgcolor = white
+textcolor = #222222
+linkcolor = #0090c0
+visitedlinkcolor = #00608f
+headtextcolor = #1a1a1a
+headbgcolor = white
+headlinkcolor = #aaaaaa
new file mode 100644
--- /dev/null
+++ b/python/psutil/docs/conf.py
@@ -0,0 +1,262 @@
+# -*- coding: utf-8 -*-
+#
+# psutil documentation build configuration file, created by
+# sphinx-quickstart.
+#
+# This file is execfile()d with the current directory set to its
+# containing dir.
+#
+# Note that not all possible configuration values are present in this
+# autogenerated file.
+#
+# All configuration values have a default; values that are commented out
+# serve to show the default.
+
+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'")
+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:
+        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
+        else:
+            raise ValueError("couldn't find version string")
+    finally:
+        f.close()
+
+VERSION = get_version()
+
+# If your documentation needs a minimal Sphinx version, state it here.
+needs_sphinx = '1.0'
+
+# Add any Sphinx extension module names here, as strings. They can be
+# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
+# ones.
+extensions = ['sphinx.ext.autodoc',
+              'sphinx.ext.coverage',
+              'sphinx.ext.pngmath',
+              'sphinx.ext.viewcode',
+              'sphinx.ext.intersphinx']
+
+# Add any paths that contain templates here, relative to this directory.
+templates_path = ['_template']
+
+# The suffix of source filenames.
+source_suffix = '.rst'
+
+# The encoding of source files.
+# source_encoding = 'utf-8-sig'
+
+# The master toctree document.
+master_doc = 'index'
+
+# General information about the project.
+project = PROJECT_NAME
+copyright = u('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
+# built documents.
+#
+# The short X.Y version.
+version = VERSION
+
+# The language for content autogenerated by Sphinx. Refer to documentation
+# for a list of supported languages.
+# language = None
+
+# There are two options for replacing |today|: either, you set today to some
+# non-false value, then it is used:
+# today = ''
+# Else, today_fmt is used as the format for a strftime call.
+# today_fmt = '%B %d, %Y'
+
+# List of patterns, relative to source directory, that match files and
+# directories to ignore when looking for source files.
+exclude_patterns = ['_build']
+
+# The reST default role (used for this markup: `text`) to use for all
+# documents.
+# default_role = None
+
+# If true, '()' will be appended to :func: etc. cross-reference text.
+add_function_parentheses = True
+# If true, the current module name will be prepended to all description
+# unit titles (such as .. function::).
+# add_module_names = True
+
+autodoc_docstring_signature = True
+
+# If true, sectionauthor and moduleauthor directives will be shown in the
+# output. They are ignored by default.
+# show_authors = False
+
+# The name of the Pygments (syntax highlighting) style to use.
+pygments_style = 'sphinx'
+
+# A list of ignored prefixes for module index sorting.
+# modindex_common_prefix = []
+
+
+# -- Options for HTML output -------------------------------------------------
+
+# The theme to use for HTML and HTML Help pages.  See the documentation for
+# a list of builtin themes.
+
+# Theme options are theme-specific and customize the look and feel of a theme
+# further.  For a list of options available for each theme, see the
+# documentation.
+html_theme = 'pydoctheme'
+html_theme_options = {'collapsiblesidebar': True}
+
+# Add any paths that contain custom themes here, relative to this directory.
+html_theme_path = ["_themes"]
+
+# The name for this set of Sphinx documents.  If None, it defaults to
+# "<project> v<release> documentation".
+html_title = "{project} {version} documentation".format(**locals())
+
+# A shorter title for the navigation bar.  Default is the same as html_title.
+# html_short_title = None
+
+# The name of an image file (relative to this directory) to place at the top
+# of the sidebar.
+# html_logo = 'logo.png'
+
+# The name of an image file (within the static path) to use as favicon of the
+# docs.  This file should be a Windows icon file (.ico) being 16x16 or 32x32
+# pixels large.
+html_favicon = '_static/favicon.ico'
+
+# Add any paths that contain custom static files (such as style sheets) here,
+# relative to this directory. They are copied after the builtin static files,
+# so a file named "default.css" will overwrite the builtin "default.css".
+html_static_path = ['_static']
+
+# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
+# using the given strftime format.
+html_last_updated_fmt = '%b %d, %Y'
+
+# If true, SmartyPants will be used to convert quotes and dashes to
+# typographically correct entities.
+html_use_smartypants = True
+
+# Custom sidebar templates, maps document names to template names.
+html_sidebars = {
+    'index': 'indexsidebar.html',
+    '**': ['globaltoc.html',
+           'relations.html',
+           'sourcelink.html',
+           'searchbox.html']
+}
+
+# Additional templates that should be rendered to pages, maps page names to
+# template names.
+# html_additional_pages = {
+#    'index': 'indexcontent.html',
+# }
+
+# If false, no module index is generated.
+html_domain_indices = False
+
+# If false, no index is generated.
+html_use_index = True
+
+# If true, the index is split into individual pages for each letter.
+# html_split_index = False
+
+# If true, links to the reST sources are added to the pages.
+# html_show_sourcelink = True
+
+# If true, "Created using Sphinx" is shown in the HTML footer. Default is True.
+# html_show_sphinx = True
+
+# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True.
+# html_show_copyright = True
+
+# If true, an OpenSearch description file will be output, and all pages will
+# contain a <link> tag referring to it.  The value of this option must be the
+# base URL from which the finished HTML is served.
+# html_use_opensearch = ''
+
+# This is the file name suffix for HTML files (e.g. ".xhtml").
+# html_file_suffix = None
+
+# Output file base name for HTML help builder.
+htmlhelp_basename = '%s-doc' % PROJECT_NAME
+
+# -- Options for LaTeX output ------------------------------------------------
+
+# The paper size ('letter' or 'a4').
+# latex_paper_size = 'letter'
+
+# The font size ('10pt', '11pt' or '12pt').
+# latex_font_size = '10pt'
+
+# Grouping the document tree into LaTeX files. List of tuples
+# (source start file, target name, title, author, documentclass
+# [howto/manual]).
+latex_documents = [
+    ('index', '%s.tex' % PROJECT_NAME,
+     u('%s documentation') % PROJECT_NAME, AUTHOR),
+]
+
+# The name of an image file (relative to this directory) to place at
+# the top of the title page.
+# latex_logo = None
+
+# For "manual" documents, if this is true, then toplevel headings are parts,
+# not chapters.
+# latex_use_parts = False
+
+# If true, show page references after internal links.
+# latex_show_pagerefs = False
+
+# If true, show URL addresses after external links.
+# latex_show_urls = False
+
+# Additional stuff for the LaTeX preamble.
+# latex_preamble = ''
+
+# Documents to append as an appendix to all manuals.
+# latex_appendices = []
+
+# If false, no module index is generated.
+# latex_domain_indices = True
+
+
+# -- Options for manual page output ------------------------------------------
+
+# 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)
+]
+
+# If true, show URL addresses after external links.
+# man_show_urls = False
new file mode 100644
--- /dev/null
+++ b/python/psutil/docs/index.rst
@@ -0,0 +1,1247 @@
+.. module:: psutil
+   :synopsis: psutil module
+.. moduleauthor:: Giampaolo Rodola' <grodola@gmail.com>
+
+.. warning::
+
+   This documentation refers to new 2.X version of psutil.
+   Instructions on how to port existing 1.2.1 code are
+   `here <http://grodola.blogspot.com/2014/01/psutil-20-porting.html>`__.
+   Old 1.2.1 documentation is still available
+   `here <https://code.google.com/p/psutil/wiki/Documentation>`__.
+
+psutil documentation
+====================
+
+Quick links
+-----------
+
+* `Home page <https://github.com/giampaolo/psutil>`__
+* `Blog <http://grodola.blogspot.com/search/label/psutil>`__
+* `Download <https://pypi.python.org/pypi?:action=display&name=psutil#downloads>`__
+* `Forum <http://groups.google.com/group/psutil/topics>`__
+* `What's new <https://github.com/giampaolo/psutil/blob/master/HISTORY.rst>`__
+
+About
+-----
+
+From project's home page:
+
+  psutil (python system and process 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, OSX, FreeBSD** and **Sun Solaris**,
+  both **32-bit** and **64-bit** architectures, with Python versions from
+  **2.4** 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.
+
+System related functions
+========================
+
+CPU
+---
+
+.. function:: cpu_times(percpu=False)
+
+  Return system CPU times as a namedtuple.
+  Every attribute represents the seconds the CPU has spent in the given mode.
+  The attributes 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 nameduples for each logical CPU
+  on the system.
+  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.
+  Example output on Linux:
+
+    >>> import psutil
+    >>> psutil.cpu_times()
+    scputimes(user=17411.7, nice=77.99, system=3797.02, idle=51266.57, iowait=732.58, irq=0.01, softirq=142.43, steal=0.0, guest=0.0, guest_nice=0.0)
+
+.. function:: 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.
+  That means the first time this is called it will return a meaningless ``0.0``
+  value which you are supposed to 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.
+
+    >>> import psutil
+    >>> # blocking
+    >>> psutil.cpu_percent(interval=1)
+    2.0
+    >>> # non-blocking (percentage since last call)
+    >>> psutil.cpu_percent(interval=None)
+    2.9
+    >>> # blocking, per-cpu
+    >>> psutil.cpu_percent(interval=1, percpu=True)
+    [2.0, 1.0]
+    >>>
+
+  .. warning::
+
+    the first time this function is called with *interval* = ``0.0`` or ``None``
+    it will return a meaningless ``0.0`` value which you are supposed to
+    ignore.
+
+.. function:: cpu_times_percent(interval=None, percpu=False)
+
+  Same as :func:`cpu_percent()` but provides utilization percentages for each
+  specific CPU time as is returned by
+  :func:`psutil.cpu_times(percpu=True)<cpu_times()>`.
+  *interval* and
+  *percpu* arguments have the same meaning as in :func:`cpu_percent()`.
+
+  .. warning::
+
+    the first time this function is called with *interval* = ``0.0`` or
+    ``None`` it will return a meaningless ``0.0`` value which you are supposed
+    to ignore.
+
+.. function:: cpu_count(logical=True)
+
+    Return the number of logical CPUs in the system (same as
+    `os.cpu_count() <http://docs.python.org/3/library/os.html#os.cpu_count>`__
+    in Python 3.4).
+    If *logical* is ``False`` return the number of physical cores only (hyper
+    thread CPUs are excluded). Return ``None`` if undetermined.
+
+      >>> import psutil
+      >>> psutil.cpu_count()
+      4
+      >>> psutil.cpu_count(logical=False)
+      2
+      >>>
+
+Memory
+------
+
+.. function:: 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 actual amount of available memory that can be given
+    instantly to processes that request more memory in bytes; this is
+    calculated by summing different memory values depending on the platform
+    (e.g. free + buffers + cached on Linux) 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.
+  - **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**: (Linux, BSD): cache for things like file system metadata.
+  - **cached**: (Linux, BSD): cache for various things.
+  - **wired**: (BSD, OSX): 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.
+  See `examples/meminfo.py <https://github.com/giampaolo/psutil/blob/master/examples/meminfo.py>`__
+  script providing an example on how to convert bytes in a human readable form.
+
+    >>> import psutil
+    >>> mem = psutil.virtual_memory()
+    >>> mem
+    svmem(total=8374149120L, available=1247768576L, percent=85.1, used=8246628352L, free=127520768L, active=3208777728, inactive=1133408256, buffers=342413312L, cached=777834496)
+    >>>
+    >>> THRESHOLD = 100 * 1024 * 1024  # 100MB
+    >>> if mem.available <= THRESHOLD:
+    ...     print("warning")
+    ...
+    >>>
+
+
+.. function:: 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**: the number of bytes the system has swapped in from disk
+    (cumulative)
+  * **sout**: the number of bytes the system has swapped out from disk
+    (cumulative)
+
+  **sin** and **sout** on Windows are meaningless and are always set to ``0``.
+  See `examples/meminfo.py <https://github.com/giampaolo/psutil/blob/master/examples/meminfo.py>`__
+  script providing an example on how to convert bytes in a human readable form.
+
+    >>> import psutil
+    >>> psutil.swap_memory()
+    sswap(total=2097147904L, used=886620160L, free=1210527744L, percent=42.3, sin=1050411008, sout=1906720768)
+
+Disks
+-----
+
+.. function:: disk_partitions(all=False)
+
+  Return all mounted disk partitions as a list of namedtuples including device,
+  mount point and filesystem type, similarly to "df" command on UNIX. If *all*
+  parameter is ``False`` return physical devices only (e.g. hard disks, cd-rom
+  drives, USB keys) and ignore all others (e.g. memory partitions such as
+  `/dev/shm <http://www.cyberciti.biz/tips/what-is-devshm-and-its-practical-usage.html>`__).
+  Namedtuple's **fstype** field is a string which varies depending on the
+  platform.
+  On Linux it can be one of the values found in /proc/filesystems (e.g.
+  ``'ext3'`` for an ext3 hard drive o ``'iso9660'`` for the CD-ROM drive).
+  On Windows it is determined via
+  `GetDriveType <http://msdn.microsoft.com/en-us/library/aa364939(v=vs.85).aspx>`__
+  and can be either ``"removable"``, ``"fixed"``, ``"remote"``, ``"cdrom"``,
+  ``"unmounted"`` or ``"ramdisk"``. On OSX and FreeBSD it is retrieved via
+  `getfsstat(2) <http://www.manpagez.com/man/2/getfsstat/>`__. See
+  `disk_usage.py <https://github.com/giampaolo/psutil/blob/master/examples/disk_usage.py>`__
+  script providing an example usage.
+
+    >>> import psutil
+    >>> psutil.disk_partitions()
+    [sdiskpart(device='/dev/sda3', mountpoint='/', fstype='ext4', opts='rw,errors=remount-ro'),
+     sdiskpart(device='/dev/sda7', mountpoint='/home', fstype='ext4', opts='rw')]
+
+.. function:: 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.
+  `OSError <http://docs.python.org/3/library/exceptions.html#OSError>`__ is
+  raised if *path* does not exist. See
+  `examples/disk_usage.py <https://github.com/giampaolo/psutil/blob/master/examples/disk_usage.py>`__
+  script providing an example usage. Starting from
+  `Python 3.3 <http://bugs.python.org/issue12442>`__  this is also
+  available as
+  `shutil.disk_usage() <http://docs.python.org/3/library/shutil.html#shutil.disk_usage>`__.
+  See
+  `disk_usage.py <https://github.com/giampaolo/psutil/blob/master/examples/disk_usage.py>`__
+  script providing an example usage.
+
+    >>> import psutil
+    >>> psutil.disk_usage('/')
+    sdiskusage(total=21378641920, used=4809781248, free=15482871808, percent=22.5)
+
+.. function:: disk_io_counters(perdisk=False)
+
+  Return system-wide 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 milliseconds)
+  - **write_time**: time spent writing to disk (in milliseconds)
+
+  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 namedutuple described above as the values.
+  See `examples/iotop.py <https://github.com/giampaolo/psutil/blob/master/examples/iotop.py>`__
+  for an example application.
+
+    >>> import psutil
+    >>> psutil.disk_io_counters()
+    sdiskio(read_count=8141, write_count=2431, read_bytes=290203, write_bytes=537676, read_time=5868, write_time=94922)
+    >>>
+    >>> psutil.disk_io_counters(perdisk=True)
+    {'sda1': sdiskio(read_count=920, write_count=1, read_bytes=2933248, write_bytes=512, read_time=6016, write_time=4),
+     'sda2': sdiskio(read_count=18707, write_count=8830, read_bytes=6060, write_bytes=3443, read_time=24585, write_time=1572),
+     'sdb1': sdiskio(read_count=161, write_count=0, read_bytes=786432, write_bytes=0, read_time=44, write_time=0)}
+
+Network
+-------
+
+.. function:: net_io_counters(pernic=False)
+
+  Return system-wide network I/O statistics as a namedtuple including the
+  following attributes:
+
+  - **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 OSX 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.
+  See `examples/nettop.py <https://github.com/giampaolo/psutil/blob/master/examples/nettop.py>`__
+  for an example application.
+
+    >>> import psutil
+    >>> psutil.net_io_counters()
+    snetio(bytes_sent=14508483, bytes_recv=62749361, packets_sent=84311, packets_recv=94888, errin=0, errout=0, dropin=0, dropout=0)
+    >>>
+    >>> psutil.net_io_counters(pernic=True)
+    {'lo': snetio(bytes_sent=547971, bytes_recv=547971, packets_sent=5075, packets_recv=5075, errin=0, errout=0, dropin=0, dropout=0),
+    'wlan0': snetio(bytes_sent=13921765, bytes_recv=62162574, packets_sent=79097, packets_recv=89648, errin=0, errout=0, dropin=0, dropout=0)}
+
+.. function:: net_connections(kind='inet')
+
+  Return system-wide socket connections as a list of namedutples.
+  Every namedtuple provides 7 attributes:
+
+  - **fd**: the socket file descriptor, if retrievable, else ``-1``.
+    If the connection refers to the current process this may be passed to
+    `socket.fromfd() <http://docs.python.org/library/socket.html#socket.fromfd>`__
+    to obtain a usable socket object.
+  - **family**: the address family, either `AF_INET
+    <http://docs.python.org//library/socket.html#socket.AF_INET>`__,
+    `AF_INET6 <http://docs.python.org//library/socket.html#socket.AF_INET6>`__
+    or `AF_UNIX <http://docs.python.org//library/socket.html#socket.AF_UNIX>`__.
+  - **type**: the address type, either `SOCK_STREAM
+    <http://docs.python.org//library/socket.html#socket.SOCK_STREAM>`__ or
+    `SOCK_DGRAM
+    <http://docs.python.org//library/socket.html#socket.SOCK_DGRAM>`__.
+  - **laddr**: the local address as a ``(ip, port)`` tuple or a ``path``
+    in case of AF_UNIX sockets.
+  - **raddr**: the remote address as a ``(ip, port)`` tuple or an absolute
+    ``path`` in case of UNIX sockets.
+    When the remote endpoint is not connected you'll get an empty tuple
+    (AF_INET*) or ``None`` (AF_UNIX).
+    On Linux AF_UNIX sockets will always have this set to ``None``.
+  - **status**: represents the status of a TCP connection. The return value
+    is one of the :data:`psutil.CONN_* <psutil.CONN_ESTABLISHED>` constants
+    (a string).
+    For UDP and UNIX sockets this is always going to be
+    :const:`psutil.CONN_NONE`.
+  - **pid**: the PID of the process which opened the socket, if retrievable,
+    else ``None``. On some platforms (e.g. Linux) the availability of this
+    field changes depending on process privileges (root is needed).
+
+  The *kind* parameter is a string which filters for connections that fit the
+  following criteria:
+
+  .. table::
+
+   +----------------+-----------------------------------------------------+
+   | **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  |
+   +----------------+-----------------------------------------------------+
+
+  To get per-process connections use :meth:`Process.connections`.
+  Also, see
+  `netstat.py sample script <https://github.com/giampaolo/psutil/blob/master/examples/netstat.py>`__.
+  Example:
+
+    >>> import psutil
+    >>> psutil.net_connections()
+    [pconn(fd=115, family=2, type=1, laddr=('10.0.0.1', 48776), raddr=('93.186.135.91', 80), status='ESTABLISHED', pid=1254),
+     pconn(fd=117, family=2, type=1, laddr=('10.0.0.1', 43761), raddr=('72.14.234.100', 80), status='CLOSING', pid=2987),
+     pconn(fd=-1, family=2, type=1, laddr=('10.0.0.1', 60759), raddr=('72.14.234.104', 80), status='ESTABLISHED', pid=None),
+     pconn(fd=-1, family=2, type=1, laddr=('10.0.0.1', 51314), raddr=('72.14.234.83', 443), status='SYN_SENT', pid=None)
+     ...]
+
+  .. note:: (OSX) :class:`psutil.AccessDenied` is always raised unless running
+     as root (lsof does the same).
+  .. note:: (Solaris) UNIX sockets are not supported.
+
+  *New in 2.1.0*
+
+
+Other system info
+-----------------
+
+.. function:: 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,
+    else ``None``.
+  - **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.
+
+  Example::
+
+    >>> import psutil
+    >>> psutil.users()
+    [suser(name='giampaolo', terminal='pts/2', host='localhost', started=1340737536.0),
+     suser(name='giampaolo', terminal='pts/3', host='localhost', started=1340737792.0)]
+
+.. function:: boot_time()
+
+  Return the system boot time expressed in seconds since the epoch.
+  Example:
+
+  .. code-block:: python
+
+     >>> import psutil, datetime
+     >>> psutil.boot_time()
+     1389563460.0
+     >>> datetime.datetime.fromtimestamp(psutil.boot_time()).strftime("%Y-%m-%d %H:%M:%S")
+     '2014-01-12 22:51:00'
+
+Processes
+=========
+
+Functions
+---------
+
+.. function:: pids()
+
+  Return a list of current running PIDs. To iterate over all processes
+  :func:`process_iter()` should be preferred.
+
+.. function:: pid_exists(pid)
+
+  Check whether the given PID exists in the current process list. This is
+  faster than doing ``"pid in psutil.pids()"`` and should be preferred.
+
+.. function:: process_iter()
+
+  Return an iterator yielding a :class:`Process` class instance for all running
+  processes on the local machine.
+  Every instance is only created once and then cached into an internal table
+  which is updated every time an element is yielded.
+  Cached :class:`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.
+  This is should be preferred over :func:`psutil.pids()` for iterating over
+  processes.
+  Sorting order in which processes are returned is
+  based on their PID. Example usage::
+
+    import psutil
+
+    for proc in psutil.process_iter():
+        try:
+            pinfo = proc.as_dict(attrs=['pid', 'name'])
+        except psutil.NoSuchProcess:
+            pass
+        else:
+            print(pinfo)
+
+.. function:: wait_procs(procs, timeout=None, callback=None)
+
+  Convenience function which waits for a list of :class:`Process` instances 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 (it may be ``None``).
+  ``callback`` is a function which gets called every time a process terminates
+  (a :class:`Process` instance is passed as callback argument). Function will
+  return as soon as all processes terminate or when timeout occurs. Tipical 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::
+
+    import psutil
+
+    def on_terminate(proc):
+        print("process {} terminated".format(proc))
+
+    procs = [...]  # a list of Process instances
+    for p in procs:
+        p.terminate()
+    gone, alive = wait_procs(procs, timeout=3, callback=on_terminate)
+    for p in alive:
+        p.kill()
+
+Exceptions
+----------
+
+.. class:: Error()
+
+  Base exception class. All other exceptions inherit from this one.
+
+.. class:: NoSuchProcess(pid, name=None, msg=None)
+
+   Raised by :class:`Process` class methods when no process with the given
+   *pid* is found in the current process list or when a process no longer
+   exists. "name" is the name the process had before disappearing
+   and gets set only if :meth:`Process.name()` was previosly called.
+
+.. class:: AccessDenied(pid=None, name=None, msg=None)
+
+    Raised by :class:`Process` class methods when permission to perform an
+    action is denied. "name" is the name of the process (may be ``None``).
+
+.. class:: TimeoutExpired(seconds, pid=None, name=None, msg=None)
+
+    Raised by :meth:`Process.wait` if timeout expires and process is still
+    alive.
+
+Process class
+-------------
+
+.. class:: Process(pid=None)
+
+  Represents an OS process with the given *pid*. If *pid* is omitted current
+  process *pid* (`os.getpid() <http://docs.python.org/library/os.html#os.getpid>`__)
+  is used.
+  Raise :class:`NoSuchProcess` if *pid* does not exist.
+  When accessing methods of this class always be  prepared to catch
+  :class:`NoSuchProcess` and :class:`AccessDenied` exceptions.
+  `hash() <http://docs.python.org/2/library/functions.html#hash>`__ builtin can
+  be used against instances of this class in order to identify a process
+  univocally over time (the hash is determined by mixing process PID
+  and creation time). As such it can also be used with
+  `set()s <http://docs.python.org/2/library/stdtypes.html#types-set>`__.
+
+  .. warning::
+
+    the way this class is bound to a process is uniquely via its **PID**.
+    That means that if the :class:`Process` instance is old enough and
+    the PID has been reused by another process in the meantime you might end up
+    interacting with another process.
+    The only exceptions for which process identity is pre-emptively checked
+    (via PID + creation time) and guaranteed are for
+    :meth:`nice` (set),
+    :meth:`ionice`  (set),
+    :meth:`cpu_affinity` (set),
+    :meth:`rlimit` (set),
+    :meth:`children`,
+    :meth:`parent`,
+    :meth:`suspend`
+    :meth:`resume`,
+    :meth:`send_signal`,
+    :meth:`terminate`, and
+    :meth:`kill`
+    methods.
+    To prevent this problem for all other methods you can use
+    :meth:`is_running()` before querying the process or use
+    :func:`process_iter()` in case you're iterating over all processes.
+
+  .. attribute:: pid
+
+     The process PID.
+
+  .. method:: ppid()
+
+     The process parent pid.  On Windows the return value is cached after first
+     call.
+
+  .. method:: name()
+
+     The process name. The return value is cached after first call.
+
+  .. method:: exe()
+
+     The process executable as an absolute path.
+     On some systems this may also be an empty string.
+     The return value is cached after first call.
+
+  .. method:: cmdline()
+
+     The command line this process has been called with.
+
+  .. method:: create_time()
+
+     The process creation time as a floating point number expressed in seconds
+     since the epoch, in
+     `UTC <http://en.wikipedia.org/wiki/Coordinated_universal_time>`__.
+     The return value is cached after first call.
+
+        >>> import psutil, datetime
+        >>> p = psutil.Process()
+        >>> p.create_time()
+        1307289803.47
+        >>> datetime.datetime.fromtimestamp(p.create_time()).strftime("%Y-%m-%d %H:%M:%S")
+        '2011-03-05 18:03:52'
+
+  .. method:: as_dict(attrs=[], 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
+     :class:`Process` class's attribute names (e.g. ``['cpu_times', 'name']``)
+     else all public (read only) attributes are assumed. *ad_value* is the
+     value which gets assigned to a dict key in case :class:`AccessDenied`
+     exception is raised when retrieving that particular process information.
+
+        >>> import psutil
+        >>> p = psutil.Process()
+        >>> p.as_dict(attrs=['pid', 'name', 'username'])
+        {'username': 'giampaolo', 'pid': 12366, 'name': 'python'}
+
+  .. method:: parent()
+
+     Utility method which returns the parent process as a :class:`Process`
+     object pre-emptively checking whether PID has been reused. If no parent
+     PID is known return ``None``.
+
+  .. method:: status()
+
+     The current process status as a string. The returned string is one of the
+     :data:`psutil.STATUS_*<psutil.STATUS_RUNNING>` constants.
+
+  .. method:: cwd()
+
+     The process current working directory as an absolute path.
+
+  .. method:: username()
+
+     The name of the user that owns the process. On UNIX this is calculated by
+     using real process uid.
+
+  .. method:: uids()
+
+     The **real**, **effective** and **saved** user ids of this process as a
+     nameduple. This is the same as
+     `os.getresuid() <http://docs.python.org//library/os.html#os.getresuid>`__
+     but can be used for every process PID.
+
+     Availability: UNIX
+
+  .. method:: gids()
+
+     The **real**, **effective** and **saved** group ids of this process as a
+     nameduple. This is the same as
+     `os.getresgid() <http://docs.python.org//library/os.html#os.getresgid>`__
+     but can be used for every process PID.
+
+     Availability: UNIX
+
+  .. method:: terminal()
+
+     The terminal associated with this process, if any, else ``None``. This is
+     similar to "tty" command but can be used for every process PID.
+
+     Availability: UNIX
+
+  .. method:: nice(value=None)
+
+     Get or set process
+     `niceness <blogs.techrepublic.com.com/opensource/?p=140>`__ (priority).
+     On UNIX this is a number which usually goes from ``-20`` to ``20``.
+     The higher the nice value, the lower the priority of the process.
+
+        >>> import psutil
+        >>> p = psutil.Process()
+        >>> p.nice(10)  # set
+        >>> p.nice()  # get
+        10
+        >>>
+
+     On Windows this is available as well by using
+     `GetPriorityClass <http://msdn.microsoft.com/en-us/library/ms683211(v=vs.85).aspx>`__
+     and `SetPriorityClass <http://msdn.microsoft.com/en-us/library/ms686219(v=vs.85).aspx>`__
+     and *value* is one of the
+     :data:`psutil.*_PRIORITY_CLASS <psutil.ABOVE_NORMAL_PRIORITY_CLASS>`
+     constants.
+     Example which increases process priority on Windows:
+
+        >>> p.nice(psutil.HIGH_PRIORITY_CLASS)
+
+     Starting from `Python 3.3 <http://bugs.python.org/issue10784>`__ this
+     same functionality is available as
+     `os.getpriority() <http://docs.python.org/3/library/os.html#os.getpriority>`__
+     and
+     `os.setpriority() <http://docs.python.org/3/library/os.html#os.setpriority>`__.
+
+  .. method:: ionice(ioclass=None, value=None)
+
+     Get or set
+     `process I/O niceness <http://friedcpu.wordpress.com/2007/07/17/why-arent-you-using-ionice-yet/>`__ (priority).
+     On Linux *ioclass* is one of the
+     :data:`psutil.IOPRIO_CLASS_*<psutil.IOPRIO_CLASS_NONE>` 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).
+     The example below sets IDLE priority class for the current process,
+     meaning it will only get I/O time when no other process needs the disk:
+
+      >>> import psutil
+      >>> p = psutil.Process()
+      >>> p.ionice(psutil.IOPRIO_CLASS_IDLE)  # set
+      >>> p.ionice()  # get
+      pionice(ioclass=3, value=0)
+      >>>
+
+     On Windows only *ioclass* is used and it can be set to ``2`` (normal),
+     ``1`` (low) or ``0`` (very low).
+
+     Availability: Linux and Windows > Vista
+
+  .. method:: rlimit(resource, limits=None)
+
+     Get or set process resource limits (see
+     `man prlimit <http://linux.die.net/man/2/prlimit>`__). *resource* is one of
+     the :data:`psutil.RLIMIT_* <psutil.RLIMIT_INFINITY>` constants.
+     *limits* is a ``(soft, hard)`` tuple.
+     This is the same as `resource.getrlimit() <http://docs.python.org/library/resource.html#resource.getrlimit>`__
+     and `resource.setrlimit() <http://docs.python.org/library/resource.html#resource.setrlimit>`__
+     but can be used for every process PID and only on Linux.
+     Example:
+
+      >>> import psutil
+      >>> p = psutil.Process()
+      >>> # process may open no more than 128 file descriptors
+      >>> p.rlimit(psutil.RLIMIT_NOFILE, (128, 128))
+      >>> # process may create files no bigger than 1024 bytes
+      >>> p.rlimit(psutil.RLIMIT_FSIZE, (1024, 1024))
+      >>> # get
+      >>> p.rlimit(psutil.RLIMIT_FSIZE)
+      (1024, 1024)
+      >>>
+
+     Availability: Linux
+
+  .. method:: io_counters()
+
+     Return process I/O statistics as a namedtuple including the number of read
+     and write operations performed by the process and the amount of bytes read
+     and written. For Linux refer to
+     `/proc filesysem documentation <https://www.kernel.org/doc/Documentation/filesystems/proc.txt>`__.
+     On BSD there's apparently no way to retrieve bytes counters, hence ``-1``
+     is returned for **read_bytes** and **write_bytes** fields. OSX is not
+     supported.
+
+      >>> import psutil
+      >>> p = psutil.Process()
+      >>> p.io_counters()
+      pio(read_count=454556, write_count=3456, read_bytes=110592, write_bytes=0)
+
+     Availability: all platforms except OSX
+
+  .. method:: num_ctx_switches()
+
+     The number voluntary and involuntary context switches performed by
+     this process.
+
+  .. method:: num_fds()
+
+     The number of file descriptors used by this process.
+
+     Availability: UNIX
+
+  .. method:: num_handles()
+
+     The number of handles used by this process.
+
+     Availability: Windows
+
+  .. method:: num_threads()
+
+     The number of threads currently used by this process.
+
+  .. method:: threads()
+
+     Return threads opened by process as a list of namedtuples including thread
+     id and thread CPU times (user/system).
+
+  .. method:: cpu_times()
+
+     Return a tuple whose values are process CPU **user** and **system**
+     times which means the amount of time expressed in seconds that a process
+     has spent in
+     `user / system mode <http://stackoverflow.com/questions/556405/what-do-real-user-and-sys-mean-in-the-output-of-time1>`__.
+     This is similar to
+     `os.times() <http://docs.python.org//library/os.html#os.times>`__
+     but can be used for every process PID.
+
+  .. method:: cpu_percent(interval=None)
+
+     Return a float representing the process CPU utilization as a percentage.
+     When *interval* is > ``0.0`` compares process times to system CPU times
+     elapsed before and after the interval (blocking). When interval is ``0.0``
+     or ``None`` compares process times to system CPU times elapsed since last
+     call, returning immediately. That means the first time this is called it
+     will return a meaningless ``0.0`` value which you are supposed to ignore.
+     In this case is recommended for accuracy that this function be called a
+     second time with at least ``0.1`` seconds between calls. Example:
+
+      >>> import psutil
+      >>> p = psutil.Process()
+      >>>
+      >>> # blocking
+      >>> p.cpu_percent(interval=1)
+      2.0
+      >>> # non-blocking (percentage since last call)
+      >>> p.cpu_percent(interval=None)
+      2.9
+      >>>
+
+     .. note::
+        a percentage > 100 is legitimate as it can result from a process with
+        multiple threads running on different CPU cores.
+
+     .. warning::
+        the first time this method is called with interval = ``0.0`` or
+        ``None`` it will return a meaningless ``0.0`` value which you are
+        supposed to ignore.
+
+  .. method:: cpu_affinity(cpus=None)
+
+     Get or set process current
+     `CPU affinity <http://www.linuxjournal.com/article/6799?page=0,0>`__.
+     CPU affinity consists in telling the OS to run a certain process on a
+     limited set of CPUs only. The number of eligible CPUs can be obtained with
+     ``list(range(psutil.cpu_count()))``.
+
+      >>> import psutil
+      >>> psutil.cpu_count()
+      4
+      >>> p = psutil.Process()
+      >>> p.cpu_affinity()  # get
+      [0, 1, 2, 3]
+      >>> p.cpu_affinity([0])  # set; from now on, process will run on CPU #0 only
+      >>>
+
+     Availability: Linux, Windows
+
+  .. method:: memory_info()
+
+     Return a tuple representing RSS (Resident Set Size) and VMS (Virtual
+     Memory Size) in bytes. On UNIX *rss* and *vms* are the same values shown
+     by ps. On Windows *rss* and *vms* refer to "Mem Usage" and "VM Size"
+     columns of taskmgr.exe. For more detailed memory stats use
+     :meth:`memory_info_ex`.
+
+  .. method:: memory_info_ex()
+
+     Return a namedtuple with variable fields depending on the platform
+     representing extended memory information about the process.
+     All numbers are expressed in bytes.
+
+     +--------+---------+-------+-------+--------------------+
+     | Linux  | OSX     | BSD   | SunOS | Windows            |
+     +========+=========+=======+=======+====================+
+     | rss    | rss     | rss   | rss   | num_page_faults    |
+     +--------+---------+-------+-------+--------------------+
+     | vms    | vms     | vms   | vms   | peak_wset          |
+     +--------+---------+-------+-------+--------------------+
+     | shared | pfaults | text  |       | wset               |
+     +--------+---------+-------+-------+--------------------+
+     | text   | pageins | data  |       | peak_paged_pool    |
+     +--------+---------+-------+-------+--------------------+
+     | lib    |         | stack |       | paged_pool         |
+     +--------+---------+-------+-------+--------------------+
+     | data   |         |       |       | peak_nonpaged_pool |
+     +--------+---------+-------+-------+--------------------+
+     | dirty  |         |       |       | nonpaged_pool      |
+     +--------+---------+-------+-------+--------------------+
+     |        |         |       |       | pagefile           |
+     +--------+---------+-------+-------+--------------------+
+     |        |         |       |       | peak_pagefile      |
+     +--------+---------+-------+-------+--------------------+
+     |        |         |       |       | private            |
+     +--------+---------+-------+-------+--------------------+
+
+     Windows metrics are extracted from
+     `PROCESS_MEMORY_COUNTERS_EX <http://msdn.microsoft.com/en-us/library/windows/desktop/ms684874(v=vs.85).aspx>`__ structure.
+     Example on Linux:
+
+     >>> import psutil
+     >>> p = psutil.Process()
+     >>> p.memory_info_ex()
+     pextmem(rss=15491072, vms=84025344, shared=5206016, text=2555904, lib=0, data=9891840, dirty=0)
+
+  .. method:: memory_percent()
+
+     Compare physical system memory to process resident memory (RSS) and
+     calculate process memory utilization as a percentage.
+
+  .. method:: memory_maps(grouped=True)
+
+     Return process's mapped memory regions as a list of nameduples whose
+     fields are variable depending on the platform. As such, portable
+     applications should rely on namedtuple's `path` and `rss` fields only.
+     This method is useful to obtain a detailed representation of process
+     memory usage as explained
+     `here <http://bmaurer.blogspot.it/2006/03/memory-usage-with-smaps.html>`__.
+     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*).
+     See `examples/pmap.py <https://github.com/giampaolo/psutil/blob/master/examples/pmap.py>`__
+     for an example application.
+
+      >>> import psutil
+      >>> p = psutil.Process()
+      >>> p.memory_maps()
+      [pmmap_grouped(path='/lib/x8664-linux-gnu/libutil-2.15.so', rss=16384, anonymous=8192, swap=0),
+       pmmap_grouped(path='/lib/x8664-linux-gnu/libc-2.15.so', rss=6384, anonymous=15, swap=0),
+       pmmap_grouped(path='/lib/x8664-linux-gnu/libcrypto.so.0.1', rss=34124, anonymous=1245, swap=0),
+       pmmap_grouped(path='[heap]', rss=54653, anonymous=8192, swap=0),
+       pmmap_grouped(path='[stack]', rss=1542, anonymous=166, swap=0),
+       ...]
+      >>>
+
+  .. method:: children(recursive=False)
+
+     Return the children of this process as a list of :Class:`Process` objects,
+     pre-emptively checking whether PID has been reused. If recursive is `True`
+     return all the parent descendants.
+     Example assuming *A == this process*:
+     ::
+
+          A ─┐
+             │
+             ├─ B (child) ─┐
+             │             └─ X (grandchild) ─┐
+             │                                └─ Y (great grandchild)
+             ├─ C (child)
+             └─ D (child)
+
+          >>> 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
+     returned either as the reference to process A is lost.
+
+  .. method:: open_files()
+
+     Return regular files opened by process as a list of namedtuples including
+     the absolute file name and the file descriptor number (on Windows this is
+     always ``-1``). Example:
+
+      >>> import psutil
+      >>> f = open('file.ext', 'w')
+      >>> p = psutil.Process()
+      >>> p.open_files()
+      [popenfile(path='/home/giampaolo/svn/psutil/file.ext', fd=3)]
+
+  .. method:: connections(kind="inet")
+
+    Return socket connections opened by process as a list of namedutples.
+    To get system-wide connections use :func:`psutil.net_connections()`.
+    Every namedtuple provides 6 attributes:
+
+    - **fd**: the socket file descriptor. This can be passed to
+      `socket.fromfd() <http://docs.python.org/library/socket.html#socket.fromfd>`__
+      to obtain a usable socket object.
+      This is only available on UNIX; on Windows ``-1`` is always returned.
+    - **family**: the address family, either `AF_INET
+      <http://docs.python.org//library/socket.html#socket.AF_INET>`__,
+      `AF_INET6 <http://docs.python.org//library/socket.html#socket.AF_INET6>`__
+      or `AF_UNIX <http://docs.python.org//library/socket.html#socket.AF_UNIX>`__.
+    - **type**: the address type, either `SOCK_STREAM
+      <http://docs.python.org//library/socket.html#socket.SOCK_STREAM>`__ or
+      `SOCK_DGRAM
+      <http://docs.python.org//library/socket.html#socket.SOCK_DGRAM>`__.
+    - **laddr**: the local address as a ``(ip, port)`` tuple or a ``path``
+      in case of AF_UNIX sockets.
+    - **raddr**: the remote address as a ``(ip, port)`` tuple or an absolute
+      ``path`` in case of UNIX sockets.
+      When the remote endpoint is not connected you'll get an empty tuple
+      (AF_INET) or ``None`` (AF_UNIX).
+      On Linux AF_UNIX sockets will always have this set to ``None``.
+    - **status**: represents the status of a TCP connection. The return value
+      is one of the :data:`psutil.CONN_* <psutil.CONN_ESTABLISHED>` constants.
+      For UDP and UNIX sockets this is always going to be
+      :const:`psutil.CONN_NONE`.
+
+    The *kind* parameter is a string which filters for connections that fit the
+    following criteria:
+
+    .. table::
+
+     +----------------+-----------------------------------------------------+
+     | **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  |
+     +----------------+-----------------------------------------------------+
+
+    Example:
+
+      >>> import psutil
+      >>> p = psutil.Process(1694)
+      >>> p.name()
+      'firefox'
+      >>> p.connections()
+      [pconn(fd=115, family=2, type=1, laddr=('10.0.0.1', 48776), raddr=('93.186.135.91', 80), status='ESTABLISHED'),
+       pconn(fd=117, family=2, type=1, laddr=('10.0.0.1', 43761), raddr=('72.14.234.100', 80), status='CLOSING'),
+       pconn(fd=119, family=2, type=1, laddr=('10.0.0.1', 60759), raddr=('72.14.234.104', 80), status='ESTABLISHED'),
+       pconn(fd=123, family=2, type=1, laddr=('10.0.0.1', 51314), raddr=('72.14.234.83', 443), status='SYN_SENT')]
+
+  .. method:: is_running()
+
+     Return whether the current process is running in the current process list.
+     This is reliable also in case the process is gone and its PID reused by
+     another process, therefore it must be preferred over doing
+     ``psutil.pid_exists(p.pid)``.
+
+     .. note::
+      this will return ``True`` also if the process is a zombie
+      (``p.status() == psutil.STATUS_ZOMBIE``).
+
+  .. method:: send_signal(signal)
+
+     Send a signal to process (see
+     `signal module <http://docs.python.org//library/signal.html>`__
+     constants) pre-emptively checking whether PID has been reused.
+     This is the same as ``os.kill(pid, sig)``.
+     On Windows only **SIGTERM** is valid and is treated as an alias for
+     :meth:`kill()`.
+
+  .. method:: suspend()
+
+     Suspend process execution with **SIGSTOP** signal pre-emptively checking
+     whether PID has been reused.
+     On UNIX this is the same as ``os.kill(pid, signal.SIGSTOP)``.
+     On Windows this is done by suspending all process threads execution.
+
+  .. method:: resume()
+
+     Resume process execution with **SIGCONT** signal pre-emptively checking
+     whether PID has been reused.
+     On UNIX this is the same as ``os.kill(pid, signal.SIGCONT)``.
+     On Windows this is done by resuming all process threads execution.
+
+  .. method:: terminate()
+
+     Terminate the process with **SIGTERM** signal pre-emptively checking
+     whether PID has been reused.
+     On UNIX this is the same as ``os.kill(pid, signal.SIGTERM)``.
+     On Windows this is an alias for :meth:`kill`.
+
+  .. method:: kill()
+
+     Kill the current process by using **SIGKILL** signal pre-emptively
+     checking whether PID has been reused.
+     On UNIX this is the same as ``os.kill(pid, signal.SIGKILL)``.
+     On Windows this is done by using
+     `TerminateProcess <http://msdn.microsoft.com/en-us/library/windows/desktop/ms686714(v=vs.85).aspx>`__.
+
+  .. method:: wait(timeout=None)
+
+     Wait for process termination and if the process is a children of the
+     current one also return the 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
+     :class:`NoSuchProcess`. If *timeout* is specified and process is still
+     alive raise :class:`TimeoutExpired` exception. It can also be used in a
+     non-blocking fashion by specifying ``timeout=0`` in which case it will
+     either return immediately or raise :class:`TimeoutExpired`.
+     To wait for multiple processes use :func:`psutil.wait_procs()`.
+
+
+Popen class
+-----------
+
+.. class:: Popen(*args, **kwargs)
+
+  A more convenient interface to stdlib
+  `subprocess.Popen <http://docs.python.org/library/subprocess.html#subprocess.Popen>`__.
+  It starts a sub process and deals with it exactly as when using
+  `subprocess.Popen <http://docs.python.org/library/subprocess.html#subprocess.Popen>`__
+  but in addition it also provides all the methods of
+  :class:`psutil.Process` class in a single interface.
+  For method names common to both classes such as
+  :meth:`send_signal() <psutil.Process.send_signal()>`,
+  :meth:`terminate() <psutil.Process.terminate()>` and
+  :meth:`kill() <psutil.Process.kill()>`
+  :class:`psutil.Process` implementation takes precedence.
+  For a complete documentation refer to
+  `subprocess module documentation <http://docs.python.org/library/subprocess.html>`__.
+
+  .. note::
+
+     Unlike `subprocess.Popen <http://docs.python.org/library/subprocess.html#subprocess.Popen>`__
+     this class pre-emptively checks wheter PID has been reused on
+     :meth:`send_signal() <psutil.Process.send_signal()>`,
+     :meth:`terminate() <psutil.Process.terminate()>` and
+     :meth:`kill() <psutil.Process.kill()>`
+     so that you don't accidentally terminate another process, fixing
+     http://bugs.python.org/issue6973.
+
+  >>> 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
+  >>>
+
+Constants
+=========
+
+.. _const-pstatus:
+.. data:: STATUS_RUNNING
+          STATUS_SLEEPING
+          STATUS_DISK_SLEEP
+          STATUS_STOPPED
+          STATUS_TRACING_STOP
+          STATUS_ZOMBIE
+          STATUS_DEAD
+          STATUS_WAKE_KILL
+          STATUS_WAKING
+          STATUS_IDLE
+          STATUS_LOCKED
+          STATUS_WAITING
+
+  A set of strings representing the status of a process.
+  Returned by :meth:`psutil.Process.status()`.
+
+.. _const-conn:
+.. data:: 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
+          CONN_DELETE_TCB (Windows)
+          CONN_IDLE (Solaris)
+          CONN_BOUND (Solaris)
+
+  A set of strings representing the status of a TCP connection.
+  Returned by :meth:`psutil.Process.connections()` (`status` field).
+
+.. _const-prio:
+.. data:: ABOVE_NORMAL_PRIORITY_CLASS
+          BELOW_NORMAL_PRIORITY_CLASS
+          HIGH_PRIORITY_CLASS
+          IDLE_PRIORITY_CLASS
+          NORMAL_PRIORITY_CLASS
+          REALTIME_PRIORITY_CLASS
+
+  A set of integers representing the priority of a process on Windows (see
+  `MSDN documentation <http://msdn.microsoft.com/en-us/library/ms686219(v=vs.85).aspx>`__).
+  They can be used in conjunction with
+  :meth:`psutil.Process.nice()` to get or set process priority.
+
+  Availability: Windows
+
+.. _const-ioprio:
+.. data:: IOPRIO_CLASS_NONE
+          IOPRIO_CLASS_RT
+          IOPRIO_CLASS_BE
+          IOPRIO_CLASS_IDLE
+
+  A set of integers representing the I/O priority of a process on Linux. They
+  can be used in conjunction with :meth:`psutil.Process.ionice()` to get or set
+  process I/O priority.
+  *IOPRIO_CLASS_NONE* and *IOPRIO_CLASS_BE* (best effort) is the default for
+  any process that hasn't set a specific I/O priority.
+  *IOPRIO_CLASS_RT* (real time) means the process is given first access to the
+  disk, regardless of what else is going on in the system.
+  *IOPRIO_CLASS_IDLE* means the process will get I/O time when no-one else
+  needs the disk.
+  For further information refer to manuals of
+  `ionice <http://linux.die.net/man/1/ionice>`__
+  command line utility or
+  `ioprio_get <http://linux.die.net/man/2/ioprio_get>`__
+  system call.
+
+  Availability: Linux
+
+.. _const-rlimit:
+.. data:: RLIMIT_INFINITY
+          RLIMIT_AS
+          RLIMIT_CORE
+          RLIMIT_CPU
+          RLIMIT_DATA
+          RLIMIT_FSIZE
+          RLIMIT_LOCKS
+          RLIMIT_MEMLOCK
+          RLIMIT_MSGQUEUE
+          RLIMIT_NICE
+          RLIMIT_NOFILE
+          RLIMIT_NPROC
+          RLIMIT_RSS
+          RLIMIT_RTPRIO
+          RLIMIT_RTTIME
+          RLIMIT_RTPRIO
+          RLIMIT_SIGPENDING
+          RLIMIT_STACK
+
+  Constants used for getting and setting process resource limits to be used in
+  conjunction with :meth:`psutil.Process.rlimit()`. See
+  `man prlimit <http://linux.die.net/man/2/prlimit>`__ for futher information.
+
+  Availability: Linux
new file mode 100644
--- /dev/null
+++ b/python/psutil/docs/make.bat
@@ -0,0 +1,242 @@
+@ECHO OFF
+
+REM Command file for Sphinx documentation
+
+if "%SPHINXBUILD%" == "" (
+	set SPHINXBUILD=sphinx-build
+)
+set BUILDDIR=_build
+set ALLSPHINXOPTS=-d %BUILDDIR%/doctrees %SPHINXOPTS% .
+set I18NSPHINXOPTS=%SPHINXOPTS% .
+if NOT "%PAPER%" == "" (
+	set ALLSPHINXOPTS=-D latex_paper_size=%PAPER% %ALLSPHINXOPTS%
+	set I18NSPHINXOPTS=-D latex_paper_size=%PAPER% %I18NSPHINXOPTS%
+)
+
+if "%1" == "" goto help
+
+if "%1" == "help" (
+	:help
+	echo.Please use `make ^<target^>` where ^<target^> is one of
+	echo.  html       to make standalone HTML files
+	echo.  dirhtml    to make HTML files named index.html in directories
+	echo.  singlehtml to make a single large HTML file
+	echo.  pickle     to make pickle files
+	echo.  json       to make JSON files
+	echo.  htmlhelp   to make HTML files and a HTML help project
+	echo.  qthelp     to make HTML files and a qthelp project
+	echo.  devhelp    to make HTML files and a Devhelp project
+	echo.  epub       to make an epub
+	echo.  latex      to make LaTeX files, you can set PAPER=a4 or PAPER=letter
+	echo.  text       to make text files
+	echo.  man        to make manual pages
+	echo.  texinfo    to make Texinfo files
+	echo.  gettext    to make PO message catalogs
+	echo.  changes    to make an overview over all changed/added/deprecated items
+	echo.  xml        to make Docutils-native XML files
+	echo.  pseudoxml  to make pseudoxml-XML files for display purposes
+	echo.  linkcheck  to check all external links for integrity
+	echo.  doctest    to run all doctests embedded in the documentation if enabled
+	goto end
+)
+
+if "%1" == "clean" (
+	for /d %%i in (%BUILDDIR%\*) do rmdir /q /s %%i
+	del /q /s %BUILDDIR%\*
+	goto end
+)
+
+
+%SPHINXBUILD% 2> nul
+if errorlevel 9009 (
+	echo.
+	echo.The 'sphinx-build' command was not found. Make sure you have Sphinx
+	echo.installed, then set the SPHINXBUILD environment variable to point
+	echo.to the full path of the 'sphinx-build' executable. Alternatively you
+	echo.may add the Sphinx directory to PATH.
+	echo.
+	echo.If you don't have Sphinx installed, grab it from
+	echo.http://sphinx-doc.org/
+	exit /b 1
+)
+
+if "%1" == "html" (
+	%SPHINXBUILD% -b html %ALLSPHINXOPTS% %BUILDDIR%/html
+	if errorlevel 1 exit /b 1
+	echo.
+	echo.Build finished. The HTML pages are in %BUILDDIR%/html.
+	goto end
+)
+
+if "%1" == "dirhtml" (
+	%SPHINXBUILD% -b dirhtml %ALLSPHINXOPTS% %BUILDDIR%/dirhtml
+	if errorlevel 1 exit /b 1
+	echo.
+	echo.Build finished. The HTML pages are in %BUILDDIR%/dirhtml.
+	goto end
+)
+
+if "%1" == "singlehtml" (
+	%SPHINXBUILD% -b singlehtml %ALLSPHINXOPTS% %BUILDDIR%/singlehtml
+	if errorlevel 1 exit /b 1
+	echo.
+	echo.Build finished. The HTML pages are in %BUILDDIR%/singlehtml.
+	goto end
+)
+
+if "%1" == "pickle" (
+	%SPHINXBUILD% -b pickle %ALLSPHINXOPTS% %BUILDDIR%/pickle
+	if errorlevel 1 exit /b 1
+	echo.
+	echo.Build finished; now you can process the pickle files.
+	goto end
+)
+
+if "%1" == "json" (
+	%SPHINXBUILD% -b json %ALLSPHINXOPTS% %BUILDDIR%/json
+	if errorlevel 1 exit /b 1
+	echo.
+	echo.Build finished; now you can process the JSON files.
+	goto end
+)
+
+if "%1" == "htmlhelp" (
+	%SPHINXBUILD% -b htmlhelp %ALLSPHINXOPTS% %BUILDDIR%/htmlhelp
+	if errorlevel 1 exit /b 1
+	echo.
+	echo.Build finished; now you can run HTML Help Workshop with the ^
+.hhp project file in %BUILDDIR%/htmlhelp.
+	goto end
+)
+
+if "%1" == "qthelp" (
+	%SPHINXBUILD% -b qthelp %ALLSPHINXOPTS% %BUILDDIR%/qthelp
+	if errorlevel 1 exit /b 1
+	echo.
+	echo.Build finished; now you can run "qcollectiongenerator" with the ^
+.qhcp project file in %BUILDDIR%/qthelp, like this:
+	echo.^> qcollectiongenerator %BUILDDIR%\qthelp\psutil.qhcp
+	echo.To view the help file:
+	echo.^> assistant -collectionFile %BUILDDIR%\qthelp\psutil.ghc
+	goto end
+)
+
+if "%1" == "devhelp" (
+	%SPHINXBUILD% -b devhelp %ALLSPHINXOPTS% %BUILDDIR%/devhelp
+	if errorlevel 1 exit /b 1
+	echo.
+	echo.Build finished.
+	goto end
+)
+
+if "%1" == "epub" (
+	%SPHINXBUILD% -b epub %ALLSPHINXOPTS% %BUILDDIR%/epub
+	if errorlevel 1 exit /b 1
+	echo.
+	echo.Build finished. The epub file is in %BUILDDIR%/epub.
+	goto end
+)
+
+if "%1" == "latex" (
+	%SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex
+	if errorlevel 1 exit /b 1
+	echo.
+	echo.Build finished; the LaTeX files are in %BUILDDIR%/latex.
+	goto end
+)
+
+if "%1" == "latexpdf" (
+	%SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex
+	cd %BUILDDIR%/latex
+	make all-pdf
+	cd %BUILDDIR%/..
+	echo.
+	echo.Build finished; the PDF files are in %BUILDDIR%/latex.
+	goto end
+)
+
+if "%1" == "latexpdfja" (
+	%SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex
+	cd %BUILDDIR%/latex
+	make all-pdf-ja
+	cd %BUILDDIR%/..
+	echo.
+	echo.Build finished; the PDF files are in %BUILDDIR%/latex.
+	goto end
+)
+
+if "%1" == "text" (
+	%SPHINXBUILD% -b text %ALLSPHINXOPTS% %BUILDDIR%/text
+	if errorlevel 1 exit /b 1
+	echo.
+	echo.Build finished. The text files are in %BUILDDIR%/text.
+	goto end
+)
+
+if "%1" == "man" (
+	%SPHINXBUILD% -b man %ALLSPHINXOPTS% %BUILDDIR%/man
+	if errorlevel 1 exit /b 1
+	echo.
+	echo.Build finished. The manual pages are in %BUILDDIR%/man.
+	goto end
+)
+
+if "%1" == "texinfo" (
+	%SPHINXBUILD% -b texinfo %ALLSPHINXOPTS% %BUILDDIR%/texinfo
+	if errorlevel 1 exit /b 1
+	echo.
+	echo.Build finished. The Texinfo files are in %BUILDDIR%/texinfo.
+	goto end
+)
+
+if "%1" == "gettext" (
+	%SPHINXBUILD% -b gettext %I18NSPHINXOPTS% %BUILDDIR%/locale
+	if errorlevel 1 exit /b 1
+	echo.
+	echo.Build finished. The message catalogs are in %BUILDDIR%/locale.
+	goto end
+)
+
+if "%1" == "changes" (
+	%SPHINXBUILD% -b changes %ALLSPHINXOPTS% %BUILDDIR%/changes
+	if errorlevel 1 exit /b 1
+	echo.
+	echo.The overview file is in %BUILDDIR%/changes.
+	goto end
+)
+
+if "%1" == "linkcheck" (
+	%SPHINXBUILD% -b linkcheck %ALLSPHINXOPTS% %BUILDDIR%/linkcheck
+	if errorlevel 1 exit /b 1
+	echo.
+	echo.Link check complete; look for any errors in the above output ^
+or in %BUILDDIR%/linkcheck/output.txt.
+	goto end
+)
+
+if "%1" == "doctest" (
+	%SPHINXBUILD% -b doctest %ALLSPHINXOPTS% %BUILDDIR%/doctest
+	if errorlevel 1 exit /b 1
+	echo.
+	echo.Testing of doctests in the sources finished, look at the ^
+results in %BUILDDIR%/doctest/output.txt.
+	goto end
+)
+
+if "%1" == "xml" (
+	%SPHINXBUILD% -b xml %ALLSPHINXOPTS% %BUILDDIR%/xml
+	if errorlevel 1 exit /b 1
+	echo.
+	echo.Build finished. The XML files are in %BUILDDIR%/xml.
+	goto end
+)
+
+if "%1" == "pseudoxml" (
+	%SPHINXBUILD% -b pseudoxml %ALLSPHINXOPTS% %BUILDDIR%/pseudoxml
+	if errorlevel 1 exit /b 1
+	echo.
+	echo.Build finished. The pseudo-XML files are in %BUILDDIR%/pseudoxml.
+	goto end
+)
+
+:end
--- a/python/psutil/examples/disk_usage.py
+++ b/python/psutil/examples/disk_usage.py
@@ -1,50 +1,63 @@
 #!/usr/bin/env python
 
 # 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 examples/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._compat import print_
 
+
 def bytes2human(n):
     # http://code.activestate.com/recipes/578019
     # >>> bytes2human(10000)
     # '9.8K'
     # >>> bytes2human(100001221)
     # '95.4M'
     symbols = ('K', 'M', 'G', 'T', 'P', 'E', 'Z', 'Y')
     prefix = {}
     for i, s in enumerate(symbols):
-        prefix[s] = 1 << (i+1)*10
+        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():
     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' and 'cdrom' in part.opts:
-            # may raise ENOENT if there's no cd-rom in the drive
-            continue
+        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))
+        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())
--- a/python/psutil/examples/free.py
+++ b/python/psutil/examples/free.py
@@ -1,31 +1,42 @@
 #!/usr/bin/env python
 
 # 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 examples/free.py
+             total       used       free     shared    buffers      cache
+Mem:      10125520    8625996    1499524          0     349500    3307836
+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 % ('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),
-                             '', '', ''))
+    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()
--- a/python/psutil/examples/iotop.py
+++ b/python/psutil/examples/iotop.py
@@ -7,23 +7,38 @@
 """
 A clone of iotop (http://guichaz.free.fr/iotop/) showing real time
 disk I/O statistics.
 
 It works on Linux only (FreeBSD and OSX are missing support for IO
 counters).
 It doesn't work on Windows as curses module is required.
 
+Example output:
+
+$ python examples/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' <g.rodola@gmail.com>
 """
 
 import os
 import sys
 import psutil
-if not hasattr(psutil.Process, 'get_io_counters') or os.name != 'posix':
+if not hasattr(psutil.Process, 'io_counters') or os.name != 'posix':
     sys.exit('platform not supported')
 import time
 import curses
 import atexit
 
 
 # --- curses stuff
 def tear_down():
@@ -32,16 +47,17 @@ def tear_down():
     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:
@@ -60,50 +76,51 @@ def bytes2human(n):
     >>> bytes2human(10000)
     '9.8 K/s'
     >>> bytes2human(100001221)
     '95.4 M/s'
     """
     symbols = ('K', 'M', 'G', 'T', 'P', 'E', 'Z', 'Y')
     prefix = {}
     for i, s in enumerate(symbols):
-        prefix[s] = 1 << (i+1)*10
+        prefix[s] = 1 << (i + 1) * 10
     for s in reversed(symbols):
         if n >= prefix[s]:
             value = float(n) / prefix[s]
             return '%.2f %s/s' % (value, s)
     return '%.2f B/s' % (n)
 
+
 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.get_io_counters()
+            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[:]:
         try:
-            p._after = p.get_io_counters()
-            p._cmdline = ' '.join(p.cmdline)
+            p._after = p.io_counters()
+            p._cmdline = ' '.join(p.cmdline())
             if not p._cmdline:
-                p._cmdline = p.name
-            p._username = p.username
+                p._cmdline = p.name()
+            p._username = p.username()
         except psutil.NoSuchProcess:
             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
@@ -129,27 +146,29 @@ def refresh_window(procs, disks_read, di
     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)
+        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 1:
             args = poll(interval)
             refresh_window(*args)
             interval = 1
     except (KeyboardInterrupt, SystemExit):
--- a/python/psutil/examples/killall.py
+++ b/python/psutil/examples/killall.py
@@ -7,25 +7,26 @@
 """
 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():
+        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)
 
 sys.exit(main())
--- a/python/psutil/examples/meminfo.py
+++ b/python/psutil/examples/meminfo.py
@@ -1,31 +1,69 @@
 #!/usr/bin/env python
 
 # 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 examples/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._compat import print_
 
-def to_meg(n):
-    return str(int(n / 1024 / 1024)) + "M"
+
+def bytes2human(n):
+    # http://code.activestate.com/recipes/578019
+    # >>> bytes2human(10000)
+    # '9.8K'
+    # >>> bytes2human(100001221)
+    # '95.4M'
+    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 pprint_ntuple(nt):
     for name in nt._fields:
         value = getattr(nt, name)
         if name != 'percent':
-            value = to_meg(value)
+            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()
--- a/python/psutil/examples/netstat.py
+++ b/python/psutil/examples/netstat.py
@@ -1,52 +1,65 @@
 #!/usr/bin/env python
 
 # 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'.
+A clone of 'netstat -antp' on Linux.
+
+$ python examples/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
 from psutil._compat import print_
 
 
 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'}
+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 %-22s %-22s %-13s %-6s %s"
-    print_(templ % ("Proto", "Local addr", "Remote addr", "Status", "PID",
-                    "Program name"))
+    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():
-        name = '?'
         try:
-            name = p.name
-            cons = p.get_connections(kind='inet')
-        except psutil.AccessDenied:
-            print_(templ % (AD, AD, AD, AD, p.pid, name))
-        except psutil.NoSuchProcess:
-            continue
-        else:
-            for c in cons:
-                raddr = ""
-                laddr = "%s:%s" % (c.laddr)
-                if c.raddr:
-                    raddr = "%s:%s" % (c.raddr)
-                print_(templ % (proto_map[(c.family, c.type)],
-                                laddr,
-                                raddr,
-                                str(c.status),
-                                p.pid,
-                                name[:15]))
+            proc_names[p.pid] = p.name()
+        except psutil.Error:
+            pass
+    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()
--- a/python/psutil/examples/nettop.py
+++ b/python/psutil/examples/nettop.py
@@ -5,24 +5,43 @@
 # 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' <g.rodola@gmail.com>
+
+$ python examples/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 sys
 import os
 if os.name != 'posix':
     sys.exit('platform not supported')
+import atexit
 import curses
-import atexit
 import time
 
 import psutil
 
 
 # --- curses stuff
 def tear_down():
     win.keypad(0)
@@ -30,16 +49,17 @@ def tear_down():
     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:
@@ -58,67 +78,68 @@ def bytes2human(n):
     >>> bytes2human(10000)
     '9.8 K'
     >>> bytes2human(100001221)
     '95.4 M'
     """
     symbols = ('K', 'M', 'G', 'T', 'P', 'E', 'Z', 'Y')
     prefix = {}
     for i, s in enumerate(symbols):
-        prefix[s] = 1 << (i+1)*10
+        prefix[s] = 1 << (i + 1) * 10
     for s in reversed(symbols):
         if n >= prefix[s]:
             value = float(n) / prefix[s]
             return '%.2f %s' % (value, s)
     return '%.2f B' % (n)
 
+
 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 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)
-    )
-
+    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',
+            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',
+            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",
@@ -128,17 +149,17 @@ def refresh_window(tot_before, tot_after
         print_line("")
     win.refresh()
     lineno = 0
 
 
 def main():
     try:
         interval = 0
-        while 1:
+        while True:
             args = poll(interval)
             refresh_window(*args)
             interval = 1
     except (KeyboardInterrupt, SystemExit):
         pass
 
 if __name__ == '__main__':
     main()
--- a/python/psutil/examples/pmap.py
+++ b/python/psutil/examples/pmap.py
@@ -2,34 +2,57 @@
 
 # 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 OSX and 'procstat -v' on BSD.
 Report memory map of a process.
+
+$ python examples/pmap.py 32402
+pid=32402, name=hg
+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._compat import print_
 
+
 def main():
     if len(sys.argv) != 2:
-        sys.exit('usage: pmap pid')
+        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"))
     total_rss = 0
-    for m in p.get_memory_maps(grouped=False):
+    for m in p.memory_maps(grouped=False):
         total_rss += m.rss
-        print_(templ % (m.addr.split('-')[0].zfill(16),
-                        str(m.rss / 1024) + 'K' ,
-                        m.perms,
-                        m.path))
+        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', '', ''))
 
 if __name__ == '__main__':
     main()
--- a/python/psutil/examples/process_detail.py
+++ b/python/psutil/examples/process_detail.py
@@ -1,129 +1,157 @@
 #!/usr/bin/env python
 
 # 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' <g.rodola@gmail.com>
 
-Author: Giampaolo Rodola' <g.rodola@gmail.com>
+$ python examples/process_detail.py
+pid               820
+name              python
+exe               /usr/bin/python2.7
+parent            29613 (bash)
+cmdline           python examples/process_detail.py
+started           2014-41-27 03:41
+user              giampaolo
+uids              real=1000, effective=1000, saved=1000
+gids              real=1000, effective=1000, saved=1000
+terminal          /dev/pts/17
+cwd               /ssd/svn/psutil
+memory            0.1% (resident=10.6M, virtual=58.5M)
+cpu               0.0% (user=0.09, system=0.0)
+status            running
+niceness          0
+num threads       1
+I/O               bytes-read=0B, bytes-written=0B
+open files
+running threads   id=820, user-time=0.09, sys-time=0.0
 """
 
+import datetime
 import os
-import datetime
 import socket
 import sys
 
 import psutil
 
 
+POSIX = os.name == 'posix'
+
+
 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
+        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 print_(a, b):
-    if sys.stdout.isatty() and os.name == 'posix':
-        fmt = '\x1b[1;32m%-17s\x1b[0m %s' %(a, b)
+    if sys.stdout.isatty() and POSIX:
+        fmt = '\x1b[1;32m%-17s\x1b[0m %s' % (a, b)
     else:
-        fmt = '%-15s %s' %(a, b)
+        fmt = '%-15s %s' % (a, b)
     # python 2/3 compatibility layer
     sys.stdout.write(fmt + '\n')
     sys.stdout.flush()
 
+
 def run(pid):
     ACCESS_DENIED = ''
     try:
         p = psutil.Process(pid)
         pinfo = p.as_dict(ad_value=ACCESS_DENIED)
     except psutil.NoSuchProcess:
         sys.exit(str(sys.exc_info()[1]))
 
     try:
-        if p.parent:
-            parent = '(%s)' % p.parent.name
+        parent = p.parent()
+        if parent:
+            parent = '(%s)' % parent.name()
         else:
             parent = ''
     except psutil.Error:
         parent = ''
-    started = datetime.datetime.fromtimestamp(pinfo['create_time']
-                                                ).strftime('%Y-%M-%d %H:%M')
+    started = datetime.datetime.fromtimestamp(
+        pinfo['create_time']).strftime('%Y-%m-%d %H:%M')
     io = pinfo.get('io_counters', ACCESS_DENIED)
     mem = '%s%% (resident=%s, virtual=%s) ' % (
-                                      round(pinfo['memory_percent'], 1),
-                                      convert_bytes(pinfo['memory_info'].rss),
-                                      convert_bytes(pinfo['memory_info'].vms))
-    children = p.get_children()
+        round(pinfo['memory_percent'], 1),
+        convert_bytes(pinfo['memory_info'].rss),
+        convert_bytes(pinfo['memory_info'].vms))
+    children = p.children()
 
     print_('pid', pinfo['pid'])
     print_('name', pinfo['name'])
     print_('exe', pinfo['exe'])
     print_('parent', '%s %s' % (pinfo['ppid'], parent))
     print_('cmdline', ' '.join(pinfo['cmdline']))
     print_('started', started)
     print_('user', pinfo['username'])
-    if os.name == 'posix' and pinfo['uids'] and pinfo['gids']:
+    if POSIX and pinfo['uids'] and pinfo['gids']:
         print_('uids', 'real=%s, effective=%s, saved=%s' % pinfo['uids'])
-    if os.name == 'posix' and pinfo['gids']:
+    if POSIX and pinfo['gids']:
         print_('gids', 'real=%s, effective=%s, saved=%s' % pinfo['gids'])
-    if os.name == 'posix':
+    if POSIX:
         print_('terminal', pinfo['terminal'] or '')
     if hasattr(p, 'getcwd'):
         print_('cwd', pinfo['cwd'])
     print_('memory', mem)
-    print_('cpu', '%s%% (user=%s, system=%s)' % (pinfo['cpu_percent'],
-                                    getattr(pinfo['cpu_times'], 'user', '?'),
-                                    getattr(pinfo['cpu_times'], 'system', '?')))
+    print_('cpu', '%s%% (user=%s, system=%s)' % (
+        pinfo['cpu_percent'],
+        getattr(pinfo['cpu_times'], 'user', '?'),
+        getattr(pinfo['cpu_times'], 'system', '?')))
     print_('status', pinfo['status'])
     print_('niceness', pinfo['nice'])
     print_('num threads', pinfo['num_threads'])
     if io != ACCESS_DENIED:
-        print_('I/O', 'bytes-read=%s, bytes-written=%s' % \
-                                               (convert_bytes(io.read_bytes),
-                                                convert_bytes(io.write_bytes)))
+        print_('I/O', 'bytes-read=%s, bytes-written=%s' % (
+            convert_bytes(io.read_bytes),
+            convert_bytes(io.write_bytes)))
     if children:
         print_('children', '')
         for child in children:
-            print_('', 'pid=%s name=%s' % (child.pid, child.name))
+            print_('', 'pid=%s name=%s' % (child.pid, child.name()))
 
     if pinfo['open_files'] != ACCESS_DENIED:
         print_('open files', '')
         for file in pinfo['open_files']:
-            print_('',  'fd=%s %s ' % (file.fd, file.path))
+            print_('', 'fd=%s %s ' % (file.fd, file.path))
 
     if pinfo['threads']:
         print_('running threads', '')
         for thread in pinfo['threads']:
-            print_('',  'id=%s, user-time=%s, sys-time=%s' \
-                         % (thread.id, thread.user_time, thread.system_time))
-    if pinfo['connections'] != ACCESS_DENIED:
+            print_('', 'id=%s, user-time=%s, sys-time=%s' % (
+                thread.id, thread.user_time, thread.system_time))
+    if pinfo['connections'] not in (ACCESS_DENIED, []):
         print_('open connections', '')
         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_('',  '%s:%s -> %s:%s type=%s status=%s' \
-                         % (lip, lport, rip, rport, type, conn.status))
+            print_('', '%s:%s -> %s:%s type=%s status=%s' % (
+                lip, lport, rip, rport, type, conn.status))
+
 
 def main(argv=None):
     if argv is None:
         argv = sys.argv
     if len(argv) == 1:
         sys.exit(run(os.getpid()))
     elif len(argv) == 2:
         sys.exit(run(int(argv[1])))
new file mode 100644
--- /dev/null
+++ b/python/psutil/examples/ps.py
@@ -0,0 +1,81 @@
+#!/usr/bin/env python
+
+# 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' on UNIX.
+
+$ python examples/ps.py
+...
+"""
+
+import datetime
+import os
+import time
+
+import psutil
+from psutil._compat import print_
+
+
+def main():
+    today_day = datetime.date.today()
+    templ = "%-10s %5s %4s %4s %7s %7s %-13s %5s %7s  %s"
+    attrs = ['pid', 'cpu_percent', 'memory_percent', 'name', 'cpu_times',
+             'create_time', 'memory_info']
+    if os.name == 'posix':
+        attrs.append('uids')
+        attrs.append('terminal')
+    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='')
+        except psutil.NoSuchProcess:
+            pass
+        else:
+            if pinfo['create_time']:
+                ctime = datetime.datetime.fromtimestamp(pinfo['create_time'])
+                if ctime.date() == today_day:
+                    ctime = ctime.strftime("%H:%M")
+                else:
+                    ctime = ctime.strftime("%b%d")
+            else:
+                ctime = ''
+            cputime = time.strftime("%M:%S",
+                                    time.localtime(sum(pinfo['cpu_times'])))
+            try:
+                user = p.username()
+            except KeyError:
+                if os.name == 'posix':
+                    if pinfo['uids']:
+                        user = str(pinfo['uids'].real)
+                    else:
+                        user = ''
+                else:
+                    raise
+            except psutil.Error:
+                user = ''
+            if os.name == 'nt' and '\\' in user:
+                user = user.split('\\')[1]
+            vms = pinfo['memory_info'] and \
+                int(pinfo['memory_info'].vms / 1024) or '?'
+            rss = pinfo['memory_info'] and \
+                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 '?'))
+
+
+if __name__ == '__main__':
+    main()
--- a/python/psutil/examples/top.py
+++ b/python/psutil/examples/top.py
@@ -3,25 +3,49 @@
 # 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' <g.rodola@gmail.com>
+
+$ python examples/top.py
+ CPU0  [|                                       ]   4.9%
+ CPU1  [|||                                     ]   7.8%
+ CPU2  [                                        ]   2.0%
+ CPU3  [|||||                                   ]  13.9%
+ Mem   [|||||||||||||||||||                     ]  49.8%  4920M/9888M
+ Swap  [                                        ]   0.0%     0M/0M
+ Processes: 287 (running=1 sleeping=286)
+ Load average: 0.34 0.54 0.46  Uptime: 3 days, 10:16:37
+
+PID    USER       NI  VIRT   RES   CPU% MEM%     TIME+  NAME
+------------------------------------------------------------
+989    giampaol    0   66M   12M    7.4  0.1   0:00.61  python
+2083   root        0  506M  159M    6.5  1.6   0:29.26  Xorg
+4503   giampaol    0  599M   25M    6.5  0.3   3:32.60  gnome-terminal
+3868   giampaol    0  358M    8M    2.8  0.1  23:12.60  pulseaudio
+3936   giampaol    0    1G  111M    2.8  1.1  33:41.67  compiz
+4401   giampaol    0  536M  141M    2.8  1.4  35:42.73  skype
+4047   giampaol    0  743M   76M    1.8  0.8  42:03.33  unity-panel-service
+13155  giampaol    0    1G  280M    1.8  2.8  41:57.34  chrome
+10     root        0    0B    0B    0.9  0.0   4:01.81  rcu_sched
+339    giampaol    0    1G  113M    0.9  1.1   8:15.73  chrome
+...
 """
 
 import os
 import sys
 if os.name != 'posix':
     sys.exit('platform not supported')
-import time
+import atexit
 import curses
-import atexit
+import time
 from datetime import datetime, timedelta
 
 import psutil
 
 
 # --- curses stuff
 def tear_down():
     win.keypad(0)
@@ -29,16 +53,17 @@ def tear_down():
     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:
@@ -57,56 +82,60 @@ def bytes2human(n):
     >>> bytes2human(10000)
     '9K'
     >>> bytes2human(100001221)
     '95M'
     """
     symbols = ('K', 'M', 'G', 'T', 'P', 'E', 'Z', 'Y')
     prefix = {}
     for i, s in enumerate(symbols):
-        prefix[s] = 1 << (i+1)*10
+        prefix[s] = 1 << (i + 1) * 10
     for s in reversed(symbols):
         if n >= prefix[s]:
             value = int(float(n) / prefix[s])
             return '%s%s' % (value, s)
     return "%sB" % n
 
+
 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', 'get_nice', 'get_memory_info',
-                                'get_memory_percent', 'get_cpu_percent',
-                                'get_cpu_times', 'name', 'status'])
+            p.dict = p.as_dict(['username', 'nice', 'memory_info',
+                                'memory_percent', 'cpu_percent',
+                                'cpu_times', 'name', 'status'])
             try:
-                procs_status[str(p.dict['status'])] += 1
+                procs_status[p.dict['status']] += 1
             except KeyError:
-                procs_status[str(p.dict['status'])] = 1
+                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)
+    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))
+        dashes = "|" * int((float(perc) / 10 * 4))
         empty_dashes = " " * (40 - len(dashes))
         return dashes, empty_dashes
 
     # cpu usage
-    for cpu_num, perc in enumerate(psutil.cpu_percent(interval=0, percpu=True)):
+    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)
     used = mem.total - mem.available
     line = " Mem   [%s%s] %5s%% %6s/%s" % (
         dashes, empty_dashes,
@@ -130,36 +159,37 @@ def print_header(procs_status, num_procs
     # 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.now() - datetime.fromtimestamp(psutil.BOOT_TIME)
+    uptime = datetime.now() - datetime.fromtimestamp(psutil.boot_time())
     av1, av2, av3 = os.getloadavg()
     line = " Load average: %.2f %.2f %.2f  Uptime: %s" \
-            % (av1, av2, av3, str(uptime).split('.')[0])
+        % (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 %5s %5s %6s %4s %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'] != None:
+        if p.dict['cpu_times'] is not None:
             ctime = 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)
--- a/python/psutil/examples/who.py
+++ b/python/psutil/examples/who.py
@@ -2,29 +2,33 @@
 
 # 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 examples/who.py
+giampaolo       tty7            2014-02-23 17:25  (:0)
+giampaolo       pts/7           2014-02-24 18:25  (:192.168.1.56)
+giampaolo       pts/8           2014-02-24 18:25  (:0)
+giampaolo       pts/9           2014-02-27 01:32  (:0)
 """
 
-import sys
 from datetime import datetime
 
 import psutil
 from psutil._compat import print_
 
 
 def main():
-    users = psutil.get_users()
+    users = psutil.users()
     for user in users:
-        print_("%-15s %-15s %s  (%s)" % \
-            (user.name,
-             user.terminal or '-',
-             datetime.fromtimestamp(user.started).strftime("%Y-%m-%d %H:%M"),
-             user.host)
-        )
+        print_("%-15s %-15s %s  (%s)" % (
+            user.name,
+            user.terminal or '-',
+            datetime.fromtimestamp(user.started).strftime("%Y-%m-%d %H:%M"),
+            user.host))
 
 if __name__ == '__main__':
     main()
new file mode 100644
--- /dev/null
+++ b/python/psutil/make.bat
@@ -0,0 +1,230 @@
+@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 - 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.
+rem
+rem By default C:\Python27\python.exe is used.
+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%" == "" (
+    set PYTHON=C:\Python27\python.exe
+)
+if "%TSCRIPT%" == "" (
+    set TSCRIPT=test\test_psutil.py
+)
+
+rem Needed to compile using Mingw.
+set PATH=C:\MinGW\bin;%PATH%
+
+rem Needed to locate the .pypirc file and upload exes on PYPI.
+set HOME=%USERPROFILE%
+
+rem ==========================================================================
+
+if "%1" == "help" (
+    :help
+    echo Run `make ^<target^>` where ^<target^> is one of:
+    echo   build         compile without installing
+    echo   build-exes    create exe installers in dist directory
+    echo   build-wheels  create wheel installers in dist directory
+    echo   clean         clean build files
+    echo   install       compile and install
+    echo   memtest       run memory leak tests
+    echo   setup-env     install pip, unittest2, wheels for all python versions
+    echo   test          run tests
+    echo   test-process  run process related tests
+    echo   test-system   run system APIs related tests
+    echo   uninstall     uninstall
+    echo   upload-exes   upload exe installers on pypi
+    echo   upload-wheels upload wheel installers on pypi
+    goto :eof
+)
+
+if "%1" == "clean" (
+    :clean
+    for /r %%R in (__pycache__) do if exist %%R (rmdir /S /Q %%R)
+    for /r %%R in (*.pyc) do if exist %%R (del /s %%R)
+    for /r %%R in (*.pyd) do if exist %%R (del /s %%R)
+    for /r %%R in (*.orig) do if exist %%R (del /s %%R)
+    for /r %%R in (*.bak) do if exist %%R (del /s %%R)
+    for /r %%R in (*.rej) do if exist %%R (del /s %%R)
+    if exist psutil.egg-info (rmdir /S /Q psutil.egg-info)
+    if exist build (rmdir /S /Q build)
+    if exist dist (rmdir /S /Q dist)
+    goto :eof
+)
+
+if "%1" == "build" (
+    :build
+    if %PYTHON%==C:\Python24\python.exe (
+        %PYTHON% setup.py build -c mingw32
+    ) else if %PYTHON%==C:\Python25\python.exe (
+        %PYTHON% setup.py build -c mingw32
+    ) else (
+        %PYTHON% setup.py build
+    )
+    if %errorlevel% neq 0 goto :error
+    goto :eof
+)
+
+if "%1" == "install" (
+    :install
+    if %PYTHON%==C:\Python24\python.exe (
+        %PYTHON% setup.py build -c mingw32 install
+    ) else if %PYTHON%==C:\Python25\python.exe (
+        %PYTHON% setup.py build -c mingw32 install
+    ) else (
+        %PYTHON% setup.py build install
+    )
+    goto :eof
+)
+
+if "%1" == "uninstall" (
+    :uninstall
+    for %%A in ("%PYTHON%") do (
+        set folder=%%~dpA
+    )
+    for /F "delims=" %%i in ('dir /b %folder%\Lib\site-packages\*psutil*') do (
+        rmdir /S /Q %folder%\Lib\site-packages\%%i
+    )
+    goto :eof
+)
+
+if "%1" == "test" (
+    :test
+    call :install
+    %PYTHON% %TSCRIPT%
+    goto :eof
+)
+
+if "%1" == "test-process" (
+    :test
+    call :install
+    %PYTHON% -m unittest -v test.test_psutil.TestProcess
+    goto :eof
+)
+
+if "%1" == "test-system" (
+    :test
+    call :install
+    %PYTHON% -m unittest -v test.test_psutil.TestSystem
+    goto :eof
+)
+
+if "%1" == "test-memleaks" (
+    :memtest
+    call :install
+    %PYTHON% test\test_memory_leaks.py
+    goto :eof
+)
+
+if "%1" == "build-exes" (
+    :build-exes
+    rem mingw 32 versions
+    C:\Python24\python.exe setup.py build -c mingw32 bdist_wininst || goto :error
+    C:\Python25\python.exe setup.py build -c mingw32 bdist_wininst || goto :error
+    rem "standard" 32 bit versions, using VS 2008 (2.6, 2.7) or VS 2010 (3.3+)
+    C:\Python26\python.exe setup.py build bdist_wininst || goto :error
+    C:\Python27\python.exe setup.py build bdist_wininst || goto :error
+    C:\Python33\python.exe setup.py build bdist_wininst || goto :error
+    C:\Python34\python.exe setup.py build bdist_wininst || goto :error
+    rem 64 bit versions
+    rem Python 2.7 + VS 2008 requires vcvars64.bat to be run first:
+    rem http://stackoverflow.com/questions/11072521/
+    rem Windows SDK and .NET Framework 3.5 SP1 also need to be installed (sigh)
+    "C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\bin\vcvars64.bat"
+    C:\Python27-64\python.exe setup.py build bdist_wininst || goto :error
+    C:\Python33-64\python.exe setup.py build bdist_wininst || goto :error
+    C:\Python34-64\python.exe setup.py build bdist_wininst || goto :error
+    echo OK
+    goto :eof
+)
+
+if "%1" == "upload-exes" (
+    :upload-exes
+    rem mingw 32 versions
+    C:\Python25\python.exe setup.py build -c mingw32 bdist_wininst upload || goto :error
+    rem "standard" 32 bit versions, using VS 2008 (2.6, 2.7) or VS 2010 (3.3+)
+    C:\Python26\python.exe setup.py bdist_wininst upload || goto :error
+    C:\Python27\python.exe setup.py bdist_wininst upload || goto :error
+    C:\Python33\python.exe setup.py bdist_wininst upload || goto :error
+    C:\Python34\python.exe setup.py bdist_wininst upload || goto :error
+    rem 64 bit versions
+    C:\Python27-64\python.exe setup.py build bdist_wininst upload || goto :error
+    C:\Python33-64\python.exe setup.py build bdist_wininst upload || goto :error
+    C:\Python34-64\python.exe setup.py build bdist_wininst upload || goto :error
+    echo OK
+    goto :eof
+)
+
+if "%1" == "setup-env" (
+    :setup-env
+    C:\python27\python.exe -c "import urllib2; url = urllib2.urlopen('https://raw.github.com/pypa/pip/master/contrib/get-pip.py'); data = url.read(); f = open('get-pip.py', 'w'); f.write(data)"
+    C:\python26\python.exe get-pip.py & C:\python26\scripts\pip install unittest2 wheel --upgrade
+    C:\python27\python.exe get-pip.py & C:\python27\scripts\pip install wheel --upgrade
+    C:\python33\python.exe get-pip.py & C:\python33\scripts\pip install wheel --upgrade
+    C:\python34\scripts\easy_install.exe wheel
+    rem 64-bit versions
+    C:\python27-64\python.exe get-pip.py & C:\python27-64\scripts\pip install wheel --upgrade
+    C:\python33-64\python.exe get-pip.py & C:\python33-64\scripts\pip install wheel --upgrade
+    C:\python34-64\scripts\easy_install.exe wheel
+    goto :eof
+)
+
+if "%1" == "build-wheels" (
+    :build-wheels
+    C:\Python26\python.exe setup.py build bdist_wheel || goto :error
+    C:\Python27\python.exe setup.py build bdist_wheel || goto :error
+    C:\Python33\python.exe setup.py build bdist_wheel || goto :error
+    C:\Python34\python.exe setup.py build bdist_wheel || goto :error
+    rem 64 bit versions
+    rem Python 2.7 + VS 2008 requires vcvars64.bat to be run first:
+    rem http://stackoverflow.com/questions/11072521/
+    rem Windows SDK and .NET Framework 3.5 SP1 also need to be installed (sigh)
+    "C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\bin\vcvars64.bat"
+    C:\Python27-64\python.exe setup.py build bdist_wheel || goto :error
+    C:\Python33-64\python.exe setup.py build bdist_wheel || goto :error
+    C:\Python34-64\python.exe setup.py build bdist_wheel || goto :error
+    echo OK
+    goto :eof
+)
+
+if "%1" == "upload-wheels" (
+    :build-wheels
+    C:\Python26\python.exe setup.py build bdist_wheel upload || goto :error
+    C:\Python27\python.exe setup.py build bdist_wheel upload || goto :error
+    C:\Python33\python.exe setup.py build bdist_wheel upload || goto :error
+    C:\Python34\python.exe setup.py build bdist_wheel upload || goto :error
+    rem 64 bit versions
+    rem Python 2.7 + VS 2008 requires vcvars64.bat to be run first:
+    rem http://stackoverflow.com/questions/11072521/
+    rem Windows SDK and .NET Framework 3.5 SP1 also need to be installed (sigh)
+    "C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\bin\vcvars64.bat"
+    C:\Python27-64\python.exe setup.py build bdist_wheel upload || goto :error
+    C:\Python33-64\python.exe setup.py build bdist_wheel upload || goto :error
+    C:\Python34-64\python.exe setup.py build bdist_wheel upload || goto :error
+    echo OK
+    goto :eof
+)
+
+goto :help
+
+:error
+    echo last command exited with error code %errorlevel%
+    exit /b %errorlevel%
+    goto :eof
--- a/python/psutil/psutil/__init__.py
+++ b/python/psutil/psutil/__init__.py
@@ -1,903 +1,1268 @@
 #!/usr/bin/env python
 # -*- 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 module providing convenience functions for managing
-processes and gather system information in a portable way by using
-Python.
+"""psutil is a cross-platform library for retrieving information on
+running processes and system utilization (CPU, memory, disks, network)
+in Python.
 """
 
 from __future__ import division
 
-__version__ = "1.0.1"
+__author__ = "Giampaolo Rodola'"
+__version__ = "2.1.3"
 version_info = tuple([int(num) for num in __version__.split('.')])
 
 __all__ = [
     # exceptions
     "Error", "NoSuchProcess", "AccessDenied", "TimeoutExpired",
     # constants
-    "NUM_CPUS", "TOTAL_PHYMEM", "BOOT_TIME",
     "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_WAKING", "STATUS_LOCKED", "STATUS_WAITING", "STATUS_LOCKED",
     "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",
     # classes
     "Process", "Popen",
     # functions
-    "pid_exists", "get_pid_list", "process_iter",                   # proc
+    "pid_exists", "pids", "process_iter", "wait_procs",             # proc
     "virtual_memory", "swap_memory",                                # memory
-    "cpu_times", "cpu_percent", "cpu_times_percent",                # cpu
-    "net_io_counters",                                              # network
+    "cpu_times", "cpu_percent", "cpu_times_percent", "cpu_count",   # cpu
+    "net_io_counters", "net_connections",                           # network
     "disk_io_counters", "disk_partitions", "disk_usage",            # disk
-    "get_users", "get_boot_time",                                   # others
-    ]
+    "users", "boot_time",                                           # others
+]
 
 import sys
 import os
 import time
 import signal
 import warnings
 import errno
 import subprocess
 try:
     import pwd
 except ImportError:
     pwd = None
 
-from psutil._error import Error, NoSuchProcess, AccessDenied, TimeoutExpired
-from psutil._common import cached_property
-from psutil._compat import (property, callable, defaultdict, namedtuple,
-                            wraps as _wraps, PY3 as _PY3)
-from psutil._common import (deprecated as _deprecated,
-                            nt_disk_iostat as _nt_disk_iostat,
-                            nt_net_iostat as _nt_net_iostat,
-                            nt_sysmeminfo as _nt_sysmeminfo,
-                            isfile_strict as _isfile_strict)
-from psutil._common import (STATUS_RUNNING, STATUS_IDLE, STATUS_SLEEPING,
-                            STATUS_DISK_SLEEP, STATUS_STOPPED,
-                            STATUS_TRACING_STOP, STATUS_ZOMBIE, STATUS_DEAD,
-                            STATUS_WAKING, STATUS_LOCKED,
-                            #
-                            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)
+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._common import (deprecated_method as _deprecated_method,
+                            deprecated as _deprecated,
+                            sdiskio as _nt_sys_diskio,
+                            snetio as _nt_sys_netio)
 
-# import the appropriate module for our platform only
+from psutil._common import (STATUS_RUNNING,  # NOQA
+                            STATUS_SLEEPING,
+                            STATUS_DISK_SLEEP,
+                            STATUS_STOPPED,
+                            STATUS_TRACING_STOP,
+                            STATUS_ZOMBIE,
+                            STATUS_DEAD,
+                            STATUS_WAKING,
+                            STATUS_LOCKED,
+                            STATUS_IDLE,  # bsd
+                            STATUS_WAITING,  # bsd
+                            STATUS_LOCKED)  # bsd
+
+from psutil._common import (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)
+
 if sys.platform.startswith("linux"):
     import psutil._pslinux as _psplatform
-    from psutil._pslinux import (phymem_buffers,
-                                 cached_phymem,
-                                 IOPRIO_CLASS_NONE,
+    from psutil._pslinux import (phymem_buffers,  # NOQA
+                                 cached_phymem)
+
+    from psutil._pslinux import (IOPRIO_CLASS_NONE,  # NOQA
                                  IOPRIO_CLASS_RT,
                                  IOPRIO_CLASS_BE,
                                  IOPRIO_CLASS_IDLE)
-    phymem_buffers = _psplatform.phymem_buffers
-    cached_phymem = _psplatform.cached_phymem
+    # Linux >= 2.6.36
+    if _psplatform.HAS_PRLIMIT:
+        from _psutil_linux import (RLIM_INFINITY,  # NOQA
+                                   RLIMIT_AS,
+                                   RLIMIT_CORE,
+                                   RLIMIT_CPU,
+                                   RLIMIT_DATA,
+                                   RLIMIT_FSIZE,
+                                   RLIMIT_LOCKS,
+                                   RLIMIT_MEMLOCK,
+                                   RLIMIT_NOFILE,
+                                   RLIMIT_NPROC,
+                                   RLIMIT_RSS,
+                                   RLIMIT_STACK)
+        # Kinda ugly but considerably faster than using hasattr() and
+        # setattr() against the module object (we are at import time:
+        # speed matters).
+        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
+        del _psutil_linux
 
 elif sys.platform.startswith("win32"):
-    import psutil._psmswindows as _psplatform
-    from psutil._psmswindows import (ABOVE_NORMAL_PRIORITY_CLASS,
-                                     BELOW_NORMAL_PRIORITY_CLASS,
-                                     HIGH_PRIORITY_CLASS,
-                                     IDLE_PRIORITY_CLASS,
-                                     NORMAL_PRIORITY_CLASS,
-                                     REALTIME_PRIORITY_CLASS,
-                                     CONN_DELETE_TCB)
+    import psutil._pswindows as _psplatform
+    from _psutil_windows import (ABOVE_NORMAL_PRIORITY_CLASS,  # NOQA
+                                 BELOW_NORMAL_PRIORITY_CLASS,
+                                 HIGH_PRIORITY_CLASS,
+                                 IDLE_PRIORITY_CLASS,
+                                 NORMAL_PRIORITY_CLASS,
+                                 REALTIME_PRIORITY_CLASS)
+    from psutil._pswindows import CONN_DELETE_TCB  # NOQA
 
 elif sys.platform.startswith("darwin"):
     import psutil._psosx as _psplatform
 
 elif sys.platform.startswith("freebsd"):
     import psutil._psbsd as _psplatform
 
 elif sys.platform.startswith("sunos"):
     import psutil._pssunos as _psplatform
-    from psutil._pssunos import (CONN_IDLE,
+    from psutil._pssunos import (CONN_IDLE,  # NOQA
                                  CONN_BOUND)
 
 else:
     raise NotImplementedError('platform %s is not supported' % sys.platform)
 
 __all__.extend(_psplatform.__extra__all__)
 
-NUM_CPUS = _psplatform.NUM_CPUS
-BOOT_TIME = _psplatform.BOOT_TIME
-TOTAL_PHYMEM = _psplatform.TOTAL_PHYMEM
+
+_TOTAL_PHYMEM = None
+_POSIX = os.name == 'posix'
+_WINDOWS = os.name == 'nt'
+_timer = getattr(time, 'monotonic', time.time)
+
+
+# =====================================================================
+# --- exceptions
+# =====================================================================
+
+class Error(Exception):
+    """Base exception class. All other psutil exceptions inherit
+    from this one.
+    """
+
+
+class NoSuchProcess(Error):
+    """Exception raised when a process with a certain PID doesn't
+    or no longer exists (zombie).
+    """
+
+    def __init__(self, pid, name=None, msg=None):
+        Error.__init__(self)
+        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 __str__(self):
+        return self.msg
+
+
+class AccessDenied(Error):
+    """Exception raised when permission to perform an action is denied."""
 
+    def __init__(self, pid=None, name=None, msg=None):
+        Error.__init__(self)
+        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 = ""
+
+    def __str__(self):
+        return self.msg
+
+
+class TimeoutExpired(Error):
+    """Raised on Process.wait(timeout) if timeout expires and process
+    is still alive.
+    """
+
+    def __init__(self, seconds, pid=None, name=None):
+        Error.__init__(self)
+        self.seconds = seconds
+        self.pid = pid
+        self.name = name
+        self.msg = "timeout after %s seconds" % seconds
+        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
+
+    def __str__(self):
+        return self.msg
+
+# push exception classes into platform specific module namespace
+_psplatform.NoSuchProcess = NoSuchProcess
+_psplatform.AccessDenied = AccessDenied
+_psplatform.TimeoutExpired = TimeoutExpired
+
+
+# =====================================================================
+# --- Process class
+# =====================================================================
 
 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)
     def wrapper(self, *args, **kwargs):
         if not self.is_running():
-            raise NoSuchProcess(self.pid, self._platform_impl._process_name)
+            raise NoSuchProcess(self.pid, self._name)
         return fun(self, *args, **kwargs)
     return wrapper
 
 
 class Process(object):
-    """Represents an OS process."""
+    """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.
 
-    def __init__(self, pid):
-        """Create a new Process object for the given pid.
-        Raises 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.
 
-        Note that most of the methods of this class do not make sure
-        the PID of the process being queried has been reused.
-        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()
 
-        The only exceptions for which process identity is pre-emptively
-        checked are:
-         - parent
-         - get_children()
-         - set_nice()
-         - 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)
 
-        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
-        """
-        if not _PY3:
-            if not isinstance(pid, (int, long)):
-                raise TypeError('pid must be an integer')
-        if pid < 0:
-            raise ValueError('pid must be a positive integer')
+    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
+        # used for caching on Windows only (on POSIX ppid may change)
         self._ppid = None
         # platform-specific modules define an _psplatform.Process
         # implementation class
-        self._platform_impl = _psplatform.Process(pid)
+        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
+            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 NoSuchProcess:
-            raise NoSuchProcess(pid, None, 'no process found with pid %s' % pid)
+            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:
             pid = self.pid
-            name = repr(self.name)
+            name = repr(self.name())
         except NoSuchProcess:
             details = "(pid=%s (terminated))" % self.pid
         except AccessDenied:
             details = "(pid=%s)" % (self.pid)
         else:
             details = "(pid=%s, name=%s)" % (pid, name)
         return "%s.%s%s" % (self.__class__.__module__,
                             self.__class__.__name__, details)
 
     def __repr__(self):
         return "<%s at %s>" % (self.__str__(), id(self))
 
+    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
+
     # --- utility methods
 
     def as_dict(self, attrs=[], ad_value=None):
-        """Utility method returning process information as a hashable
-        dictionary.
+        """Utility method returning process information as a
+        hashable dictionary.
 
-        If 'attrs' is specified it must be a list of strings reflecting
-        available Process class's attribute names (e.g. ['get_cpu_times',
-        'name']) else all public (read only) attributes are assumed.
+        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 to a dict key in case
-        AccessDenied exception is raised when retrieving that particular
-        process information.
+        'ad_value' is the value which gets assigned in case
+        AccessDenied  exception is raised when retrieving that
+        particular process information.
         """
-        excluded_names = set(['send_signal', 'suspend', 'resume', 'terminate',
-                              'kill', 'wait', 'is_running', 'as_dict', 'parent',
-                              'get_children', 'nice'])
+        excluded_names = set(
+            ['send_signal', 'suspend', 'resume', 'terminate', 'kill', 'wait',
+             'is_running', 'as_dict', 'parent', 'children', 'rlimit'])
         retdict = dict()
-        for name in set(attrs or dir(self)):
+        ls = set(attrs or [x for x in dir(self) if not x.startswith('get')])
+        for name in ls:
             if name.startswith('_'):
                 continue
             if name.startswith('set_'):
                 continue
+            if name.startswith('get_'):
+                msg = "%s() is deprecated; use %s() instead" % (name, name[4:])
+                warnings.warn(msg, category=DeprecationWarning, stacklevel=2)
+                name = name[4:]
+                if name in ls:
+                    continue
+            if name == 'getcwd':
+                msg = "getcwd() is deprecated; use cwd() instead"
+                warnings.warn(msg, category=DeprecationWarning, stacklevel=2)
+                name = 'cwd'
+                if name in ls:
+                    continue
+
             if name in excluded_names:
                 continue
             try:
                 attr = getattr(self, name)
                 if callable(attr):
-                    if name == 'get_cpu_percent':
-                        ret = attr(interval=0)
-                    else:
-                        ret = attr()
+                    ret = attr()
                 else:
                     ret = attr
             except AccessDenied:
                 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
-            if name.startswith('get'):
-                if name[3] == '_':
-                    name = name[4:]
-                elif name == 'getcwd':
-                    name = 'cwd'
             retdict[name] = ret
         return retdict
 
-    @property
-    @_assert_pid_not_reused
     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.
         """
-        ppid = self.ppid
+        ppid = self.ppid()
         if ppid is not None:
             try:
                 parent = Process(ppid)
-                if parent.create_time <= self.create_time:
+                if parent.create_time() <= self.create_time():
                     return parent
                 # ...else ppid has been reused by another process
             except NoSuchProcess:
                 pass
 
+    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
+            # check process identity.
+            # Process identity / uniqueness over time is greanted by
+            # (PID + creation time) and that is verified in __eq__.
+            return self == Process(self.pid)
+        except NoSuchProcess:
+            self._gone = True
+            return False
+
     # --- actual API
 
     @property
     def pid(self):
-        """The process pid."""
+        """The process PID."""
         return self._pid
 
-    @property
     def ppid(self):
-        """The process parent pid."""
+        """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://code.google.com/p/psutil/issues/detail?id=321
+        # 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 os.name == 'posix':
-            return self._platform_impl.get_process_ppid()
+        # Process.parent()?
+        if _POSIX:
+            return self._proc.ppid()
         else:
             if self._ppid is None:
-                self._ppid = self._platform_impl.get_process_ppid()
+                self._ppid = self._proc.ppid()
             return self._ppid
 
-    @cached_property
     def name(self):
-        """The process name."""
-        name = self._platform_impl.get_process_name()
-        if os.name == 'posix':
-            # 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
-        # XXX - perhaps needs refactoring
-        self._platform_impl._process_name = name
-        return name
+        """The process name. The return value is cached after first call."""
+        if self._name is None:
+            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._proc._name = name
+            self._name = name
+        return self._name
 
-    @cached_property
     def exe(self):
-        """The process executable path. May also be an empty string."""
+        """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
+            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):
+                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
 
-        try:
-            exe = self._platform_impl.get_process_exe()
-        except AccessDenied:
-            err = sys.exc_info()[1]
-            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
-            return exe
+        if self._exe is None:
+            try:
+                exe = self._proc.exe()
+            except AccessDenied:
+                err = sys.exc_info()[1]
+                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
 
-    @property
     def cmdline(self):
-        """The command line process has been called with."""
-        return self._platform_impl.get_process_cmdline()
+        """The command line this process has been called with."""
+        return self._proc.cmdline()
 
-    @property
     def status(self):
         """The process current status as a STATUS_* constant."""
-        return self._platform_impl.get_process_status()
-
-    if os.name == 'posix':
-
-        @property
-        def uids(self):
-            """Return a named tuple denoting the process real,
-            effective, and saved user ids.
-            """
-            return self._platform_impl.get_process_uids()
+        return self._proc.status()
 
-        @property
-        def gids(self):
-            """Return a named tuple denoting the process real,
-            effective, and saved group ids.
-            """
-            return self._platform_impl.get_process_gids()
-
-        @property
-        def terminal(self):
-            """The terminal associated with this process, if any,
-            else None.
-            """
-            return self._platform_impl.get_process_terminal()
-
-    @property
     def username(self):
         """The name of the user that owns the process.
         On UNIX this is calculated by using *real* process uid.
         """
-        if os.name == 'posix':
+        if _POSIX:
             if pwd is None:
                 # might happen if python was installed from sources
-                raise ImportError("requires pwd module shipped with standard python")
-            return pwd.getpwuid(self.uids.real).pw_name
+                raise ImportError(
+                    "requires pwd module shipped with standard python")
+            return pwd.getpwuid(self.uids().real).pw_name
         else:
-            return self._platform_impl.get_process_username()
+            return self._proc.username()
 
-    @cached_property
     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.
         """
-        return self._platform_impl.get_process_create_time()
+        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:
 
-    def getcwd(self):
-        """Return a string representing the process current working
-        directory.
-        """
-        return self._platform_impl.get_process_cwd()
+        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 and Windows only
-    if hasattr(_psplatform.Process, "get_process_io_counters"):
-
-        def get_io_counters(self):
-            """Return process I/O statistics as a namedtuple including
-            the number of read/write calls performed and the amount of
-            bytes read and written by the process.
-            """
-            return self._platform_impl.get_process_io_counters()
-
-    def get_nice(self):
-        """Get process niceness (priority)."""
-        return self._platform_impl.get_process_nice()
+    if hasattr(_psplatform.Process, "io_counters"):
 
-    @_assert_pid_not_reused
-    def set_nice(self, value):
-        """Set process niceness (priority) pre-emptively checking
-        whether PID has been reused."""
-        return self._platform_impl.set_process_nice(value)
-
-    # available only on Linux and Windows >= Vista
-    if hasattr(_psplatform.Process, "get_process_ionice"):
+        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()
 
-        def get_ionice(self):
-            """Return process I/O niceness (priority).
-
-            On Linux this is a (ioclass, value) namedtuple.
-            On Windows it's an integer which can be equal to 2 (normal),
-            1 (low) or 0 (very low).
+    # Linux and Windows >= Vista only
+    if hasattr(_psplatform.Process, "ionice_get"):
 
-            Available on Linux and Windows > Vista only.
-            """
-            return self._platform_impl.get_process_ionice()
-
-        def set_ionice(self, ioclass, value=None):
-            """Set process I/O niceness (priority).
+        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.
             """
-            return self._platform_impl.set_process_ionice(ioclass, value)
+            if ioclass is None:
+                if value is not None:
+                    raise ValueError("'ioclass' must be specified")
+                return self._proc.ionice_get()
+            else:
+                return self._proc.ionice_set(ioclass, value)
 
-    # available on Windows and Linux only
-    if hasattr(_psplatform.Process, "get_process_cpu_affinity"):
+    # Linux only
+    if hasattr(_psplatform.Process, "rlimit"):
 
-        def get_cpu_affinity(self):
-            """Get process current CPU affinity."""
-            return self._platform_impl.get_process_cpu_affinity()
+        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.
 
-        def set_cpu_affinity(self, cpus):
-            """Set process current CPU affinity.
-            'cpus' is a list of CPUs for which you want to set the
-            affinity (e.g. [0, 1]).
+            See "man prlimit" for further info.
+            Available on Linux only.
             """
-            return self._platform_impl.set_process_cpu_affinity(cpus)
+            if limits is None:
+                return self._proc.rlimit(resource)
+            else:
+                return self._proc.rlimit(resource, limits)
+
+    # Windows and Linux only
+    if hasattr(_psplatform.Process, "cpu_affinity_get"):
 
-    if os.name == 'nt':
+        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 cpus is None:
+                return self._proc.cpu_affinity_get()
+            else:
+                self._proc.cpu_affinity_set(cpus)
 
-        def get_num_handles(self):
+    if _WINDOWS:
+
+        def num_handles(self):
             """Return the number of handles opened by this process
             (Windows only).
             """
-            return self._platform_impl.get_num_handles()
-
-    if os.name == 'posix':
+            return self._proc.num_handles()
 
-        def get_num_fds(self):
-            """Return the number of file descriptors opened by this
-            process (POSIX only).
-            """
-            return self._platform_impl.get_num_fds()
+    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 get_num_ctx_switches(self):
-        """Return the number voluntary and involuntary context switches
-        performed by this process.
-        """
-        return self._platform_impl.get_num_ctx_switches()
-
-    def get_num_threads(self):
+    def num_threads(self):
         """Return the number of threads used by this process."""
-        return self._platform_impl.get_process_num_threads()
+        return self._proc.num_threads()
 
-    def get_threads(self):
-        """Return threads opened by process as a list of namedtuples
-        including thread id and thread CPU times (user/system).
+    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).
         """
-        return self._platform_impl.get_process_threads()
+        return self._proc.threads()
 
     @_assert_pid_not_reused
-    def get_children(self, recursive=False):
+    def children(self, recursive=False):
         """Return the children of this process as a list of Process
-        objects pre-emptively checking whether PID has been reused.
+        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)
 
-        >>> p.get_children()
+        >>> import psutil
+        >>> p = psutil.Process()
+        >>> p.children()
         B, C, D
-        >>> p.get_children(recursive=True)
+        >>> p.children(recursive=True)
         B, X, Y, C, D
 
         Note that in the example above if process X disappears
-        process Y won't be returned either as the reference to
-        process A is lost.
+        process Y won't be listed as the reference to process A
+        is lost.
         """
+        if hasattr(_psplatform, 'ppid_map'):
+            # Windows only: obtain a {pid:ppid, ...} dict for all running
+            # processes in one shot (faster).
+            ppid_map = _psplatform.ppid_map()
+        else:
+            ppid_map = None
+
         ret = []
         if not recursive:
-            for p in process_iter():
-                try:
-                    if p.ppid == self.pid:
-                        # if child happens to be older than its parent
-                        # (self) it means child's PID has been reused
-                        if self.create_time <= p.create_time:
-                            ret.append(p)
-                except NoSuchProcess:
-                    pass
+            if ppid_map is None:
+                # 'slow' version, common to all platforms except Windows
+                for p in process_iter():
+                    try:
+                        if p.ppid() == self.pid:
+                            # if child happens to be older than its parent
+                            # (self) it means child's PID has been reused
+                            if self.create_time() <= p.create_time():
+                                ret.append(p)
+                    except NoSuchProcess:
+                        pass
+            else:
+                # Windows only (faster)
+                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:
+                            pass
         else:
             # construct a dict where 'values' are all the processes
             # having 'key' as their parent
             table = defaultdict(list)
-            for p in process_iter():
-                try:
-                    table[p.ppid].append(p)
-                except NoSuchProcess:
-                    pass
+            if ppid_map is None:
+                for p in process_iter():
+                    try:
+                        table[p.ppid()].append(p)
+                    except NoSuchProcess:
+                        pass
+            else:
+                for pid, ppid in ppid_map.items():
+                    try:
+                        p = Process(pid)
+                        table[ppid].append(p)
+                    except NoSuchProcess:
+                        pass
             # At this point we have a mapping table where table[self.pid]
-            # are the current process's children.
+            # are the current process' children.
             # Below, we look for all descendants recursively, similarly
             # to a recursive function call.
             checkpids = [self.pid]
             for pid in checkpids:
                 for child in table[pid]:
                     try:
                         # 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
+                        intime = self.create_time() <= child.create_time()
                     except NoSuchProcess:
                         pass
                     else:
                         if intime:
                             ret.append(child)
                             if child.pid not in checkpids:
                                 checkpids.append(child.pid)
         return ret
 
-    def get_cpu_percent(self, interval=0.1):
+    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).
 
-        When interval is 0.0 or None compares process times to system
-        CPU times elapsed since last call, returning immediately
-        (non-blocking).
         In this case is recommended for accuracy that this function
         be called with at least 0.1 seconds between calls.
 
         Examples:
 
+          >>> import psutil
           >>> p = psutil.Process(os.getpid())
           >>> # blocking
-          >>> p.get_cpu_percent(interval=1)
+          >>> p.cpu_percent(interval=1)
           2.0
           >>> # non-blocking (percentage since last call)
-          >>> p.get_cpu_percent(interval=0)
+          >>> p.cpu_percent(interval=None)
           2.9
           >>>
         """
         blocking = interval is not None and interval > 0.0
+        num_cpus = cpu_count()
+        if _POSIX:
+            timer = lambda: _timer() * num_cpus
+        else:
+            timer = lambda: sum(cpu_times())
         if blocking:
-            st1 = sum(cpu_times())
-            pt1 = self._platform_impl.get_cpu_times()
+            st1 = timer()
+            pt1 = self._proc.cpu_times()
             time.sleep(interval)
-            st2 = sum(cpu_times())
-            pt2 = self._platform_impl.get_cpu_times()
+            st2 = timer()
+            pt2 = self._proc.cpu_times()
         else:
             st1 = self._last_sys_cpu_times
             pt1 = self._last_proc_cpu_times
-            st2 = sum(cpu_times())
-            pt2 = self._platform_impl.get_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:
-            # the utilization split between all CPUs
-            overall_percent = (delta_proc / delta_time) * 100
+            # The utilization split between all CPUs.
+            # Note: a percentage > 100 is legitimate as it can result
+            # from a process with multiple threads running on different
+            # CPU cores, see:
+            # http://stackoverflow.com/questions/1032357
+            # https://github.com/giampaolo/psutil/issues/474
+            overall_percent = ((delta_proc / delta_time) * 100) * num_cpus
         except ZeroDivisionError:
             # interval was too low
             return 0.0
-        # the utilization of a single CPU
-        single_cpu_percent = overall_percent * NUM_CPUS
-        # on posix a percentage > 100 is legitimate
-        # http://stackoverflow.com/questions/1032357/comprehending-top-cpu-usage
-        # on windows we use this ugly hack to avoid troubles with float
-        # precision issues
-        if os.name != 'posix':
-            if single_cpu_percent > 100.0:
-                return 100.0
-        return round(single_cpu_percent, 1)
+        else:
+            return round(overall_percent, 1)
 
-    def get_cpu_times(self):
-        """Return a tuple whose values are process CPU user and system
-        times. The same as os.times() but per-process.
+    def cpu_times(self):
+        """Return a (user, system) namedtuple representing  the
+        accumulated process time, in seconds.
+        This is the same as os.times() but per-process.
         """
-        return self._platform_impl.get_cpu_times()
+        return self._proc.cpu_times()
 
-    def get_memory_info(self):
+    def memory_info(self):
         """Return a tuple representing RSS (Resident Set Size) and VMS
         (Virtual Memory Size) in bytes.
 
-        On UNIX RSS and VMS are the same values shown by ps.
+        On UNIX RSS and VMS are the same values shown by 'ps'.
 
-        On Windows RSS and VMS refer to "Mem Usage" and "VM Size" columns
-        of taskmgr.exe.
+        On Windows RSS and VMS refer to "Mem Usage" and "VM Size"
+        columns of taskmgr.exe.
         """
-        return self._platform_impl.get_memory_info()
+        return self._proc.memory_info()
 
-    def get_ext_memory_info(self):
+    def memory_info_ex(self):
         """Return a namedtuple with variable fields depending on the
         platform representing extended memory information about
-        the process. All numbers are expressed in bytes.
+        this process. All numbers are expressed in bytes.
         """
-        return self._platform_impl.get_ext_memory_info()
+        return self._proc.memory_info_ex()
 
-    def get_memory_percent(self):
+    def memory_percent(self):
         """Compare physical system memory to process resident memory
         (RSS) and calculate process memory utilization as a percentage.
         """
-        rss = self._platform_impl.get_memory_info()[0]
+        rss = self._proc.memory_info()[0]
+        # use cached value if available
+        total_phymem = _TOTAL_PHYMEM or virtual_memory().total
         try:
-            return (rss / float(TOTAL_PHYMEM)) * 100
+            return (rss / float(total_phymem)) * 100
         except ZeroDivisionError:
             return 0.0
 
-    def get_memory_maps(self, grouped=True):
-        """Return process's mapped memory regions as a list of nameduples
+    def memory_maps(self, grouped=True):
+        """Return process' mapped memory regions as a list of nameduples
         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._platform_impl.get_memory_maps()
+        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)
+                    d[path] = map(lambda x, y: x + y, d[path], nums)
                 except KeyError:
                     d[path] = nums
-            nt = self._platform_impl.nt_mmap_grouped
-            return [nt(path, *d[path]) for path in d]
+            nt = _psplatform.pmmap_grouped
+            return [nt(path, *d[path]) for path in d]  # NOQA
         else:
-            nt = self._platform_impl.nt_mmap_ext
+            nt = _psplatform.pmmap_ext
             return [nt(*x) for x in it]
 
-    def get_open_files(self):
-        """Return files opened by process as a list of namedtuples
-        including absolute file name and file descriptor number.
+    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._platform_impl.get_open_files()
+        return self._proc.open_files()
 
-    def get_connections(self, kind='inet'):
-        """Return connections opened by process as a list of namedtuples.
-        The kind parameter filters for connections that fit the following
-        criteria:
+    def connections(self, kind='inet'):
+        """Return 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._platform_impl.get_connections(kind)
+        return self._proc.connections(kind)
 
-    def is_running(self):
-        """Return whether this process is running.
-        It also checks if PID has been reused by another process in
-        which case returns 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.
-            # pid + creation time, on the other hand, is supposed to
-            # identify a process univocally.
-            return self.create_time == \
-                   self._platform_impl.get_process_create_time()
-        except NoSuchProcess:
-            self._gone = True
-            return False
+    if _POSIX:
+        def _send_signal(self, sig):
+            try:
+                os.kill(self.pid, sig)
+            except OSError:
+                err = sys.exc_info()[1]
+                if err.errno == errno.ESRCH:
+                    self._gone = True
+                    raise NoSuchProcess(self.pid, self._name)
+                if err.errno == errno.EPERM:
+                    raise AccessDenied(self.pid, self._name)
+                raise
 
     @_assert_pid_not_reused
     def send_signal(self, sig):
         """Send a signal 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 os.name == 'posix':
-            try:
-                os.kill(self.pid, sig)
-            except OSError:
-                err = sys.exc_info()[1]
-                name = self._platform_impl._process_name
-                if err.errno == errno.ESRCH:
-                    self._gone = True
-                    raise NoSuchProcess(self.pid, name)
-                if err.errno == errno.EPERM:
-                    raise AccessDenied(self.pid, name)
-                raise
+        if _POSIX:
+            self._send_signal(sig)
         else:
             if sig == signal.SIGTERM:
-                self._platform_impl.kill_process()
+                self._proc.kill()
             else:
                 raise ValueError("only SIGTERM is supported on Windows")
 
     @_assert_pid_not_reused
     def suspend(self):
         """Suspend process execution with SIGSTOP pre-emptively checking
         whether PID has been reused.
-        On Windows it suspends all process threads.
+        On Windows this has the effect ot suspending all process threads.
         """
-        if hasattr(self._platform_impl, "suspend_process"):
-            # windows
-            self._platform_impl.suspend_process()
+        if _POSIX:
+            self._send_signal(signal.SIGSTOP)
         else:
-            # posix
-            self.send_signal(signal.SIGSTOP)
+            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 it resumes all process threads.
+        On Windows this has the effect of resuming all process threads.
         """
-        if hasattr(self._platform_impl, "resume_process"):
-            # windows
-            self._platform_impl.resume_process()
+        if _POSIX:
+            self._send_signal(signal.SIGCONT)
         else:
-            # posix
-            self.send_signal(signal.SIGCONT)
+            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().
         """
-        self.send_signal(signal.SIGTERM)
+        if _POSIX:
+            self._send_signal(signal.SIGTERM)
+        else:
+            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 os.name == 'posix':
-            self.send_signal(signal.SIGKILL)
+        whether PID has been reused.
+        """
+        if _POSIX:
+            self._send_signal(signal.SIGKILL)
         else:
-            self._platform_impl.kill_process()
+            self._proc.kill()
 
     def wait(self, timeout=None):
         """Wait for process to terminate and, if process is a children
-        of the current one also return its exit code, else None.
+        of os.getpid(), also return its exit code, else None.
+
+        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._platform_impl.process_wait(timeout)
+        return self._proc.wait(timeout)
+
+    # --- deprecated APIs
+
+    _locals = set(locals())
+
+    @_deprecated_method(replacement='children')
+    def get_children(self):
+        pass
+
+    @_deprecated_method(replacement='connections')
+    def get_connections(self):
+        pass
+
+    if "cpu_affinity" in _locals:
+        @_deprecated_method(replacement='cpu_affinity')
+        def get_cpu_affinity(self):
+            pass
+
+        @_deprecated_method(replacement='cpu_affinity')
+        def set_cpu_affinity(self, cpus):
+            pass
+
+    @_deprecated_method(replacement='cpu_percent')
+    def get_cpu_percent(self):
+        pass
 
-    # --- deprecated API
+    @_deprecated_method(replacement='cpu_times')
+    def get_cpu_times(self):
+        pass
+
+    @_deprecated_method(replacement='cwd')
+    def getcwd(self):
+        pass
+
+    @_deprecated_method(replacement='memory_info_ex')
+    def get_ext_memory_info(self):
+        pass
+
+    if "io_counters" in _locals:
+        @_deprecated_method(replacement='io_counters')
+        def get_io_counters(self):
+            pass
+
+    if "ionice" in _locals:
+        @_deprecated_method(replacement='ionice')
+        def get_ionice(self):
+            pass
+
+        @_deprecated_method(replacement='ionice')
+        def set_ionice(self, ioclass, value=None):
+            pass
+
+    @_deprecated_method(replacement='memory_info')
+    def get_memory_info(self):
+        pass
 
-    @property
-    def nice(self):
-        """Get or set process niceness (priority).
-        Deprecated, use get_nice() instead.
-        """
-        msg = "this property is deprecated; use Process.get_nice() method instead"
-        warnings.warn(msg, category=DeprecationWarning, stacklevel=2)
-        return self.get_nice()
+    @_deprecated_method(replacement='memory_maps')
+    def get_memory_maps(self):
+        pass
+
+    @_deprecated_method(replacement='memory_percent')
+    def get_memory_percent(self):
+        pass
+
+    @_deprecated_method(replacement='nice')
+    def get_nice(self):
+        pass
+
+    @_deprecated_method(replacement='num_ctx_switches')
+    def get_num_ctx_switches(self):
+        pass
+
+    if 'num_fds' in _locals:
+        @_deprecated_method(replacement='num_fds')
+        def get_num_fds(self):
+            pass
+
+    if 'num_handles' in _locals:
+        @_deprecated_method(replacement='num_handles')
+        def get_num_handles(self):
+            pass
 
-    @nice.setter
-    def nice(self, value):
-        # invoked on "p.nice = num"; change process niceness
-        # deprecated in favor of set_nice()
-        msg = "this property is deprecated; use Process.set_nice() method instead"
-        warnings.warn(msg, category=DeprecationWarning, stacklevel=2)
-        return self.set_nice(value)
+    @_deprecated_method(replacement='num_threads')
+    def get_num_threads(self):
+        pass
+
+    @_deprecated_method(replacement='open_files')
+    def get_open_files(self):
+        pass
+
+    if "rlimit" in _locals:
+        @_deprecated_method(replacement='rlimit')
+        def get_rlimit(self):
+            pass
 
+        @_deprecated_method(replacement='rlimit')
+        def set_rlimit(self, resource, limits):
+            pass
+
+    @_deprecated_method(replacement='threads')
+    def get_threads(self):
+        pass
+
+    @_deprecated_method(replacement='nice')
+    def set_nice(self, value):
+        pass
+
+    del _locals
+
+
+# =====================================================================
+# --- Popen class
+# =====================================================================
 
 class Popen(Process):
     """A more convenient interface to stdlib subprocess module.
     It starts a sub process and deals with it exactly as when using
     subprocess.Popen class but in addition also provides all the
-    property and methods of psutil.Process class in a single interface:
+    properties and methods of psutil.Process class as a unified
+    interface:
 
       >>> import psutil
       >>> from subprocess import PIPE
-      >>> p = psutil.Popen(["/usr/bin/python", "-c", "print 'hi'"], stdout=PIPE)
-      >>> p.name
+      >>> p = psutil.Popen(["python", "-c", "print 'hi'"], stdout=PIPE)
+      >>> p.name()
       'python'
-      >>> p.uids
+      >>> p.uids()
       user(real=1000, effective=1000, saved=1000)
-      >>> p.username
+      >>> 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.
 
-    For a complete documentation refers to:
+    Unlike subprocess.Popen this class pre-emptively checks wheter 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/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._pid = self.__subproc.pid
-        self._gone = False
-        self._ppid = None
-        self._platform_impl = _psplatform.Process(self._pid)
-        self._last_sys_cpu_times = None
-        self._last_proc_cpu_times = None
-        try:
-            self.create_time
-        except AccessDenied:
-            pass
-        except NoSuchProcess:
-            raise NoSuchProcess(self._pid, None,
-                                "no process found with pid %s" % self._pid)
+        self._init(self.__subproc.pid, _ignore_nsp=True)
 
     def __dir__(self):
-        return list(set(dir(Popen) + dir(subprocess.Popen)))
+        return sorted(set(dir(Popen) + dir(subprocess.Popen)))
 
     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))
+                                     % (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
 
 
 # =====================================================================
 # --- system processes related functions
 # =====================================================================
 
-get_pid_list = _psplatform.get_pid_list
-pid_exists = _psplatform.pid_exists
+def pids():
+    """Return a list of current running PIDs."""
+    return _psplatform.pids()
+
+
+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 <<every process in the process
+        # group of the calling process>> and that is not we want
+        # to do here.
+        return pid in pids()
+    else:
+        return _psplatform.pid_exists(pid)
+
 
 _pmap = {}
 
+
 def process_iter():
-    """Return a generator yielding a Process class instance for all
-    running processes on the local machine.
+    """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.
 
@@ -907,24 +1272,24 @@ def process_iter():
     def add(pid):
         proc = Process(pid)
         _pmap[proc.pid] = proc
         return proc
 
     def remove(pid):
         _pmap.pop(pid, None)
 
-    a = set(get_pid_list())
+    a = set(pids())
     b = set(_pmap.keys())
     new_pids = a - b
     gone_pids = b - a
 
     for pid in gone_pids:
         remove(pid)
-    for pid, proc in sorted(list(_pmap.items()) + \
+    for pid, proc in sorted(list(_pmap.items()) +
                             list(dict.fromkeys(new_pids).items())):
         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():
@@ -934,25 +1299,132 @@ def process_iter():
         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.
             yield proc
 
+
+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.
+
+    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():
+                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
 # =====================================================================
 
+@memoize
+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
+    (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:
+        return _psplatform.cpu_count_logical()
+    else:
+        return _psplatform.cpu_count_physical()
+
+
 def cpu_times(percpu=False):
-    """Return system-wide CPU times as a namedtuple object.
-    Every CPU time represents the time CPU has spent in the given mode.
-    The attributes availability varies depending on the platform.
-    Here follows a list of all available attributes:
+    """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