[Pymoul-svn] SF.net SVN: pymoul: [205] pymoul/trunk
Status: Alpha
Brought to you by:
tiran
|
From: <ti...@us...> - 2007-02-27 14:46:02
|
Revision: 205
http://pymoul.svn.sourceforge.net/pymoul/?rev=205&view=rev
Author: tiran
Date: 2007-02-27 06:45:53 -0800 (Tue, 27 Feb 2007)
Log Message:
-----------
Moved processinfo to external module
Modified Paths:
--------------
pymoul/trunk/INSTALL.txt
pymoul/trunk/setup.py
pymoul/trunk/src/moul/osdependent/__init__.py
pymoul/trunk/src/moul/osdependent/darwin/__init__.py
pymoul/trunk/src/moul/osdependent/linux/__init__.py
pymoul/trunk/src/moul/osdependent/win32/__init__.py
Removed Paths:
-------------
pymoul/trunk/src/moul/osdependent/processinfo.py
Modified: pymoul/trunk/INSTALL.txt
===================================================================
--- pymoul/trunk/INSTALL.txt 2007-02-27 14:32:21 UTC (rev 204)
+++ pymoul/trunk/INSTALL.txt 2007-02-27 14:45:53 UTC (rev 205)
@@ -4,9 +4,10 @@
* Python 2.5.x http://www.python.org/
* easy_install http://peak.telecommunity.com/DevCenter/EasyInstall
- * setuptools (via easy install)
- * PyTz (via $ easy_install-2.5 -Z pytz)
- * Qt4 GPL 4.2+ http://www.trolltech.com/developer/downloads/qt/
+ * setuptools (via easy_install)
+ * pytz (via $ easy_install-2.5 -Z pytz)
+ * enumprocess (via $ easy_install-2.5 -Z enumprocess)
+ * Qt4 GPL 4.2+ http://www.trolltech.com/developer/downloads/qt/
* PyQt4 4.1.1+ http://www.riverbankcomputing.co.uk/pyqt/
Windows
Modified: pymoul/trunk/setup.py
===================================================================
--- pymoul/trunk/setup.py 2007-02-27 14:32:21 UTC (rev 204)
+++ pymoul/trunk/setup.py 2007-02-27 14:45:53 UTC (rev 205)
@@ -57,7 +57,7 @@
setup_options = dict(
setup_requires = ["setuptools>="+SETUPTOOLS_VERSION,],
- install_requires = ["pytz>=2006p",],
+ install_requires = ["pytz>=2006p", "enumprocess>=0.1"],
data_files = [
('docs', list(glob('*.txt'))),
('i18n', list(glob('src/moul/qt/i18n/pymoul_*.qm'))),
Modified: pymoul/trunk/src/moul/osdependent/__init__.py
===================================================================
--- pymoul/trunk/src/moul/osdependent/__init__.py 2007-02-27 14:32:21 UTC (rev 204)
+++ pymoul/trunk/src/moul/osdependent/__init__.py 2007-02-27 14:45:53 UTC (rev 205)
@@ -38,14 +38,20 @@
import sys
from types import ModuleType
-from moul.osdependent.processinfo import getPidNames
-from moul.osdependent.processinfo import getPids
+# a program under py2exe is sys.frozen
+__FROZEN__ = bool(getattr(sys, 'frozen', False))
+if not __FROZEN__:
+ import pkg_resources
+ pkg_resources.require("enumprocess>=0.1")
+from enumprocess import getPidNames
+from enumprocess import getPids
+
+
LOG = getLogger('moul.osdependent')
-# a program under py2exe is sys.frozen
-__FROZEN__ = bool(getattr(sys, 'frozen', False))
+
# OS stuff
_plat = sys.platform.startswith
__WIN32__ = _plat('win32') # win64, cygwin?
Modified: pymoul/trunk/src/moul/osdependent/darwin/__init__.py
===================================================================
--- pymoul/trunk/src/moul/osdependent/darwin/__init__.py 2007-02-27 14:32:21 UTC (rev 204)
+++ pymoul/trunk/src/moul/osdependent/darwin/__init__.py 2007-02-27 14:45:53 UTC (rev 205)
@@ -22,11 +22,11 @@
__revision__ = "$Revision$"
import os
+from logging import getLogger
+from enumprocess import getPidNames
from subprocess import Popen
-from logging import getLogger
-
LOG = getLogger('moul.darwin')
LOG.critical('Darwin/Mac support is not tested')
Modified: pymoul/trunk/src/moul/osdependent/linux/__init__.py
===================================================================
--- pymoul/trunk/src/moul/osdependent/linux/__init__.py 2007-02-27 14:32:21 UTC (rev 204)
+++ pymoul/trunk/src/moul/osdependent/linux/__init__.py 2007-02-27 14:45:53 UTC (rev 205)
@@ -22,12 +22,11 @@
__revision__ = "$Revision$"
import os
+from logging import getLogger
+from enumprocess import getPidNames
from subprocess import Popen
-from moul.osdependent.processinfo import getPidNames
-from logging import getLogger
-
LOG = getLogger('moul.linux')
LOG.critical('Linux support is not tested')
Deleted: pymoul/trunk/src/moul/osdependent/processinfo.py
===================================================================
--- pymoul/trunk/src/moul/osdependent/processinfo.py 2007-02-27 14:32:21 UTC (rev 204)
+++ pymoul/trunk/src/moul/osdependent/processinfo.py 2007-02-27 14:45:53 UTC (rev 205)
@@ -1,465 +0,0 @@
-# pyMoul - Python interface to Myst Online URU Live
-# Copyright (C) 2007 Christian Heimes <christian (at) cheimes (dot) de>
-
-# This program is free software; you can redistribute it and/or modify it
-# under the terms of the GNU General Public License as published by the
-# Free Software Foundation; either version 2 of the License, or (at your
-# option) any later version.
-#
-# This program is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
-# more details.
-#
-# You should have received a copy of the GNU General Public License along
-# with this program; if not, write to the Free Software Foundation, Inc., 59
-# Temple Place, Suite 330, Boston, MA 02111-1307 USA
-#
-"""Get process informations
-
-The module contains for implementations:
-
- - an Unsupported implementation that raises UnsupportedError
- - a Linux implementation that read the data from /proc
- - a Unix/POSIX implementation that parses the output of ps
- - a Windows implementation that uses ctypes to get the infos from psapi.dll
-
-API
-===
- getPids() - list of ints/longs
- getPidNames() - mapping pid -> name
- getPidDetails(pid) - detailed informations about a process
- getPidDetails('self') - detailed informations about current process
-
->>> cur = os.getpid()
->>> exe = sys.executable
->>> pids = getPids()
->>> pids > 1
-True
->>> isinstance(pids[0], (int, long))
-True
->>> cur in pids
-True
-
->>> mapping = getPidNames()
->>> cur in mapping
-True
->>> mapping[cur].lower() in sys.executable
-True
-
->>> getPidDetails('self')['name'] == getPidDetails(cur)['name']
-True
->>> getPidDetails(cur)['name'] == mapping[cur]
-True
-
->>> for impl in (WinEnumProcesses(), LinuxProcReader(), PsParser()):
-... if impl.supported():
-... isinstance(impl.getPids(), list) and None
-... isinstance(impl.getPidNames(), dict) and None
-"""
-__author__ = "Christian Heimes"
-__version__ = "$Id$"
-__revision__ = "$Revision$"
-__all__ = ['getPids', 'getPidNames', 'getPidDetails', 'supportedOS',
- 'UnsupportedError']
-
-import logging
-import os
-import os.path
-import sys
-
-
-LOG = logging.getLogger("processinfo")
-NULL = "\x00"
-
-_plat = sys.platform.startswith
-if _plat('win') or _plat('cygwin'):
- from ctypes import windll, c_ulong, sizeof, c_buffer, byref
- PSAPI = windll.psapi
- KERNEL = windll.kernel32
- PROCESS_QUERY_INFORMATION = 0x0400
- PROCESS_VM_READ = 0x0010
- PROCESS_FLAGS = PROCESS_QUERY_INFORMATION | PROCESS_VM_READ
-else:
- from subprocess import Popen
- from subprocess import PIPE
-
-class UnsupportedError(OSError):
- """OS or command not supported error
- """
- pass
-
-class Unsupported(object):
- """Unsupported OS implementation
-
- Raises L{UnsupportedError}
- """
- __slots__ = ()
-
- @classmethod
- def supported(cls):
- """Supported flag property"""
- return False
-
- @classmethod
- def log(cls):
- """Log information about the implementation"""
- LOG.warning("Unsupported OS. Neither proc filesystem nor 'ps' works.")
-
- @classmethod
- def getPids(cls):
- """Get a list of pids
-
- @return: a list of pid numbers
- @rtype: list(int)
- """
- raise UnsupportedError
-
- @classmethod
- def getPidNames(cls):
- """Get a mapping of pid -> name
-
- @return: mapping of pid -> name
- @rtype: dict(int:str)
- """
- raise UnsupportedError
-
- @classmethod
- def getPidDetails(pid):
- """Get detailed informations about a process
-
- @param pid: pid number or 'self'
- @type pid: int or basestring
- @return: detailed information about a process
- @rtype: dict(str:data)
- """
- raise UnsupportedError
-
-class PsParser(object):
- """Parse the output of the ps command
- """
- __slots__ = ()
-
- CMD = "ps -e --no-header --cols=1024"
- PIDNAMES = "%s --format=pid,ucmd" % CMD
- PIDS = "%s --format=pid" % CMD
-
- @classmethod
- def supported(cls):
- """Supported flag property"""
- try:
- cls._exec(cls.PIDS)
- except Exception: # catch all!
- return False
- else:
- return True
-
- @classmethod
- def log(cls):
- """Log information about the implementation"""
- LOG.debug("Using the 'ps' command on POSIX os")
-
- @classmethod
- def getPids(cls):
- """Get a list of pids
- """
- stdout = cls._exec(cls.PIDS)
- if stdout is None:
- return None
- pids = []
- for line in stdout:
- try:
- pid = int(line.strip())
- except ValueError:
- pass
- else:
- pids.append(pid)
- return pids
-
- @classmethod
- def getPidNames(cls):
- """Get a list of pid -> name
- """
- stdout = cls._exec(cls.PIDNAMES)
- if stdout is None:
- return None
- mapping = {}
- for line in stdout:
- line = line.strip()
- idx = line.find(' ')
- pid, name = line[:idx], line[idx+1:]
- try:
- pid = int(pid)
- except ValueError:
- pass
- else:
- mapping[pid] = name
- return mapping
-
- @classmethod
- def getPidDetails(cls, pid):
- """Get detailed informations about a process
-
- TODO
- """
- if pid == 'self':
- pid = os.getpid()
- raise UnsupportedError("not implemented yet")
-
- @staticmethod
- def _exec(cmd):
- """Execute command cmd
-
- The method waits until the command has finished. It returns None of
- something went wrong.
-
- @param cmd: Command to execute
- @type cmd: str
- @return: None or stdin as file like object
- """
- try:
- popen = Popen(cmd, shell=True, bufsize=-1, stdout=PIPE,
- env = {'LC_ALL' : 'C'})
- rc = popen.wait()
- except (OSError, ValueError):
- LOG.exception("Failed to execute '%s'" % cmd)
- return None
- else:
- if rc != 0:
- LOG.error("'%s' returned with error code %i" % (cmd, rc))
- return None
- else:
- return popen.stdout
-
-class LinuxProcReader(object):
- """Get process informations under Linux by reading /proc
-
- Tested under Linux, may work on other POSIX os with /proc, too.
- """
- __slots__ = ()
-
- PROC = "/proc"
-
- @classmethod
- def supported(cls):
- return os.path.isfile("%s/self/status" % cls.PROC)
-
- @classmethod
- def log(cls):
- """Log information about the implementation"""
- LOG.debug("Using the proc filesystem on Linux")
-
- @classmethod
- def getPids(cls):
- """Get a list of pids
- """
- pids = []
- for name in os.listdir(cls.PROC):
- if os.path.isdir(cls.PROC + '/' + name):
- try:
- pids.append(int(name))
- except ValueError:
- pass
- return pids
-
- @classmethod
- def getPidNames(cls):
- """Get a list of pid -> name
- """
- mapping = {}
- for pid in cls.getPids():
- name = cls._readProcStatus(pid, searchkey='name')
- if name is not None:
- mapping[pid] = name
- return mapping
-
- def getPidDetails(cls, pid):
- """Get detailed informations about a process
- """
- details = cls._readProcStatus(pid)
- if details is None:
- return None
- details.update(cls._readProcOther(pid))
- details['cmdline'] = cls._readProcCmdline(pid)
- return details
-
- @classmethod
- def _readProcStatus(cls, pid, searchkey=None):
- """Read and parse status informations for PID pid
-
- pid - pid as long or int or 'self'
-
- If searchkey is None the method returns a mapping of lower keys
- to values (stripped).
- If searchkey is given than the method immediatly returns the value
- or returns None if they key can't be found.
- """
- mapping = {}
- status = '%s/%s/status' % (cls.PROC, pid)
- try:
- # read entiry file to avoid race conditions
- lines = open(status, 'r').readlines()
- except IOError:
- LOG.exception("%s not found" % status)
- return None
- for line in lines:
- try:
- key, value = line.split(':\t')
- except ValueError:
- continue
- key = key.lower()
- value = value.strip()
- #if value.endswith(' kB'):
- # value = value[:-3]
- if key == searchkey:
- return value
- mapping[key.lower()] = value
- if searchkey is not None:
- return None
- return mapping
-
- @classmethod
- def _readProcCmdline(cls, pid):
- """Read cmdline informations for pid and returns a list similar to sys.argv
- """
- try:
- # read entiry file to avoid race conditions
- data = open('%s/%s/cmdline' % (cls.PROC, pid), 'r').read()
- except IOError:
- return None
- return data.split(NULL)
-
- @classmethod
- def _readProcOther(cls, pid):
- """Read other possible useful things
-
- cwd -> current work directory (may not exist)
- exe -> path to executable (may not exist)
- """
- return {
- 'cwd' : os.path.realpath('%s/%s/cwd' % (cls.PROC, pid)),
- 'exe' : os.path.realpath('%s/%s/exe' % (cls.PROC, pid)),
- }
-
-class WinEnumProcesses(object):
- """""Get process informations under Win32 with psapi.dll
-
- Based on enumprocesses from Eric Koome
- http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/305279
- """
- __slots__ = ()
-
- @classmethod
- def supported(cls):
- try:
- cls.getPids()
- except Exception: # catch all!
- return False
- else:
- return True
-
- @classmethod
- def log(cls):
- """Log information about the implementation"""
- LOG.debug("Using ctypes on Windows")
-
- @classmethod
- def getPids(cls):
- """Get a list of pids
- """
- arr = c_ulong * 256
- lpidProcess = arr()
- cb = sizeof(lpidProcess)
- cbNeeded = c_ulong()
-
- # Call Enumprocesses to get hold of process id's
- PSAPI.EnumProcesses(byref(lpidProcess), cb, byref(cbNeeded))
- nReturned = cbNeeded.value/sizeof(c_ulong()) # number of processes returned
- return [pid for pid in lpidProcess][:nReturned]
-
- @classmethod
- def getPidNames(cls):
- """Get a list of pid -> name
- """
- hModule = c_ulong()
- count = c_ulong()
- modname = c_buffer(51)
- mapping = {}
- for pid in cls.getPids():
- # Get handle to the process based on PID
- hProcess = KERNEL.OpenProcess(PROCESS_FLAGS, False, pid)
- if hProcess:
- PSAPI.EnumProcessModules(hProcess, byref(hModule),
- sizeof(hModule), byref(count))
- PSAPI.GetModuleBaseNameA(hProcess, hModule.value, modname,
- sizeof(modname))
- try:
- name = u"".join([c for c in modname if c != NULL])
- except UnicodeError, msg:
- LOG.exception("Can't decode name of pid %s" % pid)
- else:
- mapping[pid] = name
- modname[:] = sizeof(modname) * NULL
- KERNEL.CloseHandle(hProcess)
-
- return mapping
-
- @classmethod
- def getPidDetails(cls, pid):
- """Get detailed informations about a process
- """
- if pid == 'self':
- pid = os.getpid()
-
- hModule = c_ulong()
- count = c_ulong()
- modname = c_buffer(51)
- hProcess = KERNEL.OpenProcess(PROCESS_FLAGS, False, pid)
- if not hProcess:
- return None
-
- PSAPI.EnumProcessModules(hProcess, byref(hModule),
- sizeof(hModule), byref(count))
- PSAPI.GetModuleBaseNameA(hProcess, hModule.value, modname,
- sizeof(modname))
- try:
- name = u"".join([c for c in modname if c != NULL])
- except UnicodeError, msg:
- LOG.exception("Can't decode name of pid %s" % pid)
- else:
- name = None
-
- KERNEL.CloseHandle(hProcess)
- return {'name' : name}
-
-
-# Initialize global methods
-_enumProcesses = None
-for impl in (WinEnumProcesses(), LinuxProcReader(), PsParser()):
- if impl.supported():
- impl.log()
- _enumProcesses = impl
- break
-
-if _enumProcesses is None:
- LOG.error("System %s is not supported" % sys.platform)
- _enumProcesses = Unsupported()
-
-getPids = _enumProcesses.getPids
-getPidNames = _enumProcesses.getPidNames
-getPidDetails = _enumProcesses.getPidDetails
-supportedOS = _enumProcesses.supported()
-
-def test_suite():
- import unittest
- from doctest import DocTestSuite
- return unittest.TestSuite((
- DocTestSuite()
- ))
-
-if __name__ == '__main__':
- import unittest
- logging.basicConfig()
- unittest.main(defaultTest="test_suite")
- print getPids()
- print getPidNames()
Modified: pymoul/trunk/src/moul/osdependent/win32/__init__.py
===================================================================
--- pymoul/trunk/src/moul/osdependent/win32/__init__.py 2007-02-27 14:32:21 UTC (rev 204)
+++ pymoul/trunk/src/moul/osdependent/win32/__init__.py 2007-02-27 14:45:53 UTC (rev 205)
@@ -22,10 +22,10 @@
__revision__ = "$Revision$"
import os
+from enumprocess import getPidNames
+from logging import getLogger
from subprocess import Popen
-from logging import getLogger
-from moul.osdependent.processinfo import getPidNames
from moul.osdependent.win32 import winpath
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|