pymoul-svn Mailing List for pyMoul (Page 9)
Status: Alpha
Brought to you by:
tiran
You can subscribe to this list here.
| 2007 |
Jan
(89) |
Feb
(108) |
Mar
(62) |
Apr
(8) |
May
(9) |
Jun
(2) |
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
|---|
|
From: <ti...@us...> - 2007-01-29 22:07:45
|
Revision: 99
http://pymoul.svn.sourceforge.net/pymoul/?rev=99&view=rev
Author: tiran
Date: 2007-01-29 14:07:42 -0800 (Mon, 29 Jan 2007)
Log Message:
-----------
First working implementation of log zipper and chatlog mover with unit tests
Modified Paths:
--------------
pymoul/trunk/Makefile.in
pymoul/trunk/src/moul/file/chatlog.py
pymoul/trunk/src/moul/file/plasmalog.py
pymoul/trunk/src/moul/file/tests/test_plasmalog.py
Modified: pymoul/trunk/Makefile.in
===================================================================
--- pymoul/trunk/Makefile.in 2007-01-29 18:46:30 UTC (rev 98)
+++ pymoul/trunk/Makefile.in 2007-01-29 22:07:42 UTC (rev 99)
@@ -59,11 +59,12 @@
doc: doc_html
clean:
- find . \( -name '*.o' -o -name '*.c' -o -name '*.so' -o -name '*.py[cod]' -o -name '*.dll' \) -exec rm -f {} \;
+ find . \( -name '*.o' -o -name '*~' -o -name '*.so' -o -name '*.py[cod]' -o -name '*.dll' \) -exec rm -f {} \;
rm -rf build
realclean: clean
rm -f TAGS
+ rm -rf dist
$(PYTHON) setup.py clean -a
propset:
Modified: pymoul/trunk/src/moul/file/chatlog.py
===================================================================
--- pymoul/trunk/src/moul/file/chatlog.py 2007-01-29 18:46:30 UTC (rev 98)
+++ pymoul/trunk/src/moul/file/chatlog.py 2007-01-29 22:07:42 UTC (rev 99)
@@ -45,8 +45,8 @@
r"^\((?P<M>\d{1,2})/(?P<D>\d{1,2})\ " # MM/DD
r"(?P<h>\d{1,2}):(?P<m>\d\d{1,2}):(?P<s>\d{1,2})\)" # hh:mm:ss
r"(?P<space>\ {1,2})(?P<msg>.*)$") # text
-CHAT_STARTED = "Chat.log started..."
-CHAT_STOPPED = "...Chat.log stopped."
+CHATLOG_STARTED = "Chat.log started..."
+CHATLOG_STOPPED = "...Chat.log stopped."
TEXT_MSGFROM = re.compile(
r"From (?P<user>.*) in (?P<location>.*): (?P<msg>.*)"
# From USER in LOCATION: msg
@@ -76,17 +76,17 @@
"""
"""
_pat = "chat*.log"
- _filename = "chatlog_%(sY)i%(sM)i%(sD)i_%(ch)i%(cm)i_%(sh)i%(sm)i.txt"
+ _filename = "chatlog_%(sY)02i%(sM)02i%(sD)02i_%(ch)02i%(cm)02i_%(sh)02i%(sm)02i.txt"
def __init__(self, srcdir, destdir):
- self._path = srcdir
- self._dest = destdir
- self._logs = []
- if not os.path.isdir(srcdir):
- LOG.critical("%s is not a directory" % srcdir)
- if not os.path.isdir(destdir):
- LOG.info("Creating chatlog directory %s" % destdir)
- os.mkdir(dest)
+ self._path = srcdir
+ self._dest = destdir
+ self._logs = []
+ if not os.path.isdir(srcdir):
+ LOG.critical("%s is not a directory" % srcdir)
+ if not os.path.isdir(destdir):
+ LOG.info("Creating chatlog directory %s" % destdir)
+ os.mkdir(destdir)
def findLogs(self):
"""Find log files in self._path
@@ -95,7 +95,7 @@
for the file.
"""
for file in os.listdir(self._path):
- if not fnmatch(file, self._pat):
+ if not fnmatch(file.lower(), self._pat):
continue
fpath = os.path.join(self._path, file)
@@ -106,13 +106,13 @@
created = self._findCreated(fd)
if not created:
LOG.warning("Failed to parse chatlog %s" % fpath)
- modtime = localtime(modtime(fpath))
- newname = self._makeFilename(created, modtime)
+ mtime = localtime(modtime(fpath))
+ newname = self._makeFilename(created, mtime)
details = {
'fpath' : fpath,
'filename' : file,
- 'modtime' : localtime(modtime(fpath)),
+ 'modtime' : mtime,
'created' : created,
'newname' : newname,
'newpath' : os.path.join(self._dest, newname),
@@ -132,8 +132,9 @@
if mo:
data = mo.groupdict()
if data['msg'].startswith(CHATLOG_STARTED):
- created = (None, mo['M'], mo['D'], mo['h'], mo['m'],
- mo['s'], None, None, None)
+ d = mo.groupdict()
+ created = (None, int(d['M']), int(d['D']), int(d['h']),
+ int(d['m']), int(d['s']), None, None, None)
return created
def _makeFilename(self, created, stopped):
@@ -141,10 +142,10 @@
"""
c, s = created, stopped
mapping = {
- 'sY' : s['Y'], 'sM' : s['YM'], 'sD' : s['D'],
- 'sh' : s['h'], 'sm' : s['m'], 'ss' : s['s'],
- 'cM' : c['YM'], 'cD' : c['D'],
- 'ch' : c['h'], 'cm' : c['m'], 'cs' : c['s'],
+ 'sY' : s[0], 'sM' : s[1], 'sD' : s[2],
+ 'sh' : s[3], 'sm' : s[4], 'ss' : s[5],
+ 'cM' : c[1], 'cD' : c[2],
+ 'ch' : c[3], 'cm' : c[4], 'cs' : c[5],
}
return self._filename % mapping
@@ -158,3 +159,7 @@
LOG.warning("%s exists - overwriting" % new)
LOG.info("Move chatlog %s to %s" % (old, new))
move(old, new)
+
+ def __call__(self):
+ self.findLogs()
+ self.moveChatlogs()
Modified: pymoul/trunk/src/moul/file/plasmalog.py
===================================================================
--- pymoul/trunk/src/moul/file/plasmalog.py 2007-01-29 18:46:30 UTC (rev 98)
+++ pymoul/trunk/src/moul/file/plasmalog.py 2007-01-29 22:07:42 UTC (rev 99)
@@ -28,8 +28,11 @@
from fnmatch import fnmatch
from moul.crypt.elf import decryptElf
+from moul.log import getLogger
PLASMA_LOG = "plasmalog.txt"
+
+LOG = getLogger('moul.plasma')
_marker = object()
class PlasmalogZipper(object):
@@ -40,38 +43,52 @@
def __init__(self, srcdir, destdir):
self._srcdir = srcdir
self._destdir = destdir
+ self._zipped_dirs = {} # dirname -> zipfile
+ self._not_removed = [] # files with full path
- def getTimeStamp(self, path):
+ if not os.path.isdir(srcdir):
+ LOG.critical("%s is not a directory" % srcdir)
+ if not self.isPlasmaLogDir():
+ self._ispldir = False
+ LOG.critical("%s is not a plasma log directory" % srcdir)
+ else:
+ self._ispldir = True
+ if not os.path.isdir(destdir):
+ LOG.info("Creating chatlog directory %s" % destdir)
+ os.mkdir(destdir)
+
+ @staticmethod
+ def getTimeStamp(path):
"""Get time stamp yyyymmdd_hhmm based in the modification time
"""
sec = os.stat(path)[ST_MTIME]
return time.strftime("%Y%m%d_%H%M", time.localtime(sec))
-
- def isLogDir(self, path):
+
+ def isPlasmaLogDir(self, path=None):
"""Check if a path is a valid plasma log directory
-
+
Just checks for the plasmalog.txt file
-
Returns either False or a time stamp
"""
+ if path is None:
+ path = self._srcdir
pl = os.path.join(path, PLASMA_LOG)
if not os.path.isfile(pl):
return False
- return getTimeStamp(pl)
+ return self.getTimeStamp(pl)
def zipLogDir(self):
"""Zip all log files
This function also zips subdirectories.
"""
- stored_dirs = []
-
for root, dirs, files in os.walk(self._srcdir):
- stamp = isLogDir(root)
+ stamp = self.isPlasmaLogDir(root)
if not stamp:
continue
name = os.path.basename(root)
zipname = "%s_%s.zip" % (name, stamp)
+ self._zipped_dirs[name] = zipname
zipfd = zipfile.ZipFile(os.path.join(self._destdir, zipname),
'w', zipfile.ZIP_DEFLATED)
for file in files:
@@ -83,24 +100,27 @@
zipfd.write(fname, arcname)
#zipfd.printdir()
zipfd.close()
- stored_dirs.append((root, zipname))
- return stored_dirs
+ def removeLogs(self):
+ """Removes log directories
- def removeLogs(self, logdir):
- """Removes log directories
-
The removeLogs function removes only files considered as safe
"""
- for root, dirs, files in os.walk(logdir, topdown=False):
+ for root, dirs, files in os.walk(self._srcdir, topdown=False):
for name in files:
matches = [pat for pat in self._save_patterns
- if fnmatch(basename, pat)]
- if match:
- os.remove(os.path.join(root, name))
+ if fnmatch(name, pat)]
+ fpath = os.path.join(root, name)
+ if matches:
+ os.remove(fpath)
else:
+ self._not_removed.append(fpath)
LOG.warning("Won't remove %s from %s" % (name, root))
for name in dirs:
os.rmdir(os.path.join(root, name))
- os.rmdir(logdir)
+ os.rmdir(self._srcdir)
+
+ def __call__(self):
+ self.zipLogDir()
+ self.removeLogs()
Modified: pymoul/trunk/src/moul/file/tests/test_plasmalog.py
===================================================================
--- pymoul/trunk/src/moul/file/tests/test_plasmalog.py 2007-01-29 18:46:30 UTC (rev 98)
+++ pymoul/trunk/src/moul/file/tests/test_plasmalog.py 2007-01-29 22:07:42 UTC (rev 99)
@@ -24,10 +24,102 @@
import unittest
from doctest import DocTestSuite
-import moul.file.plasmalog
+import os
+import shutil
+from tempfile import mkdtemp
+from moul.file.plasmalog import PlasmalogZipper
+from moul.file.chatlog import ChatlogMover
+
+FILE_LIST = ['audio.0.elf', 'audiocaps.0.elf', 'audioTimes.0.elf',
+ 'Avatar.0.elf', 'impacts.0.elf', 'LocalizationDataMgr.0.elf',
+ 'Marker.0.elf', 'NetScreener.0.elf', 'patcher.0.elf', 'pipeline.0.elf',
+ 'plasmalog.txt', 'Python.0.elf', 'Simulation.0.elf', 'voice.0.elf',
+ 'Chat.0.log']
+
+CHATLOG = """(01/02 03:04:05) Chat.log started...
+(01/02 03:04:06) Testuser: foo
+(01/02 03:04:07) ...Chat.log stopped.
+"""
+
+base = os.path.dirname(__file__)
+
+def _fakeLogdir(path):
+ """Create a fake logdir
+ """
+ if not os.path.isdir(path):
+ os.mkdir(path)
+ for fname in FILE_LIST:
+ fd = open(os.path.join(path, fname), 'w')
+ fd.write('dummy')
+ fd.close()
+
+ fd = open(os.path.join(path, 'Chat.0.log'), 'w')
+ fd.write(CHATLOG)
+ fd.close()
+ fd = open(os.path.join(path, 'plasmalog.txt'), 'w')
+ fd.write('')
+ fd.close()
+
+def _fakeUruLiveDir(path):
+ """Create a fake Uru Live directory
+ """
+ for dname in ('Avatars', 'init', 'KIimages'):
+ os.mkdir(os.path.join(path, dname))
+ _fakeLogdir(os.path.join(path, 'Logs'))
+ _fakeLogdir(os.path.join(path, 'Logs', 'faketest'))
+ shutil.copyfile(os.path.join(base, 'avatar.jpg'),
+ os.path.join(path, 'Avatars', '001.jpg'))
+ shutil.copyfile(os.path.join(base, 'graphics.ini'),
+ os.path.join(path, 'init', 'graphics.ini'))
+ shutil.copyfile(os.path.join(base, 'audio.ini'),
+ os.path.join(path, 'init', 'audio.ini'))
+
+class PlasmaChatTest(unittest.TestCase):
+ def setUp(self):
+ self._tmpdir = mkdtemp()
+ self._chatdest = os.path.join(self._tmpdir, 'Chatlogs')
+ self._logdest = os.path.join(self._tmpdir, 'ZippedLogs')
+ self._logdir = os.path.join(self._tmpdir, 'Logs')
+ _fakeUruLiveDir(self._tmpdir)
+ self._clm = ChatlogMover(self._logdir, self._chatdest)
+ self._plz = PlasmalogZipper(self._logdir, self._logdest)
+
+ def test_createDir(self):
+ self.failUnless(os.path.isdir(self._logdest), self._logdest)
+ self.failUnless(os.path.isdir(self._chatdest), self._chatdest)
+
+ def test_plasmaLogZipper(self):
+ plz = self._plz
+ self.failUnless(plz.isPlasmaLogDir())
+ plz.zipLogDir()
+ content = os.listdir(self._logdest)
+ content.sort()
+ self.failUnlessEqual(len(content), 2, content)
+ self.failUnless(content[0].startswith("Logs_"), content[0])
+ self.failUnless(content[1].startswith("faketest_"), content[1])
+
+ plz.removeLogs()
+ self.failIf(os.path.isdir(self._logdir))
+
+ def test_chatLogMover(self):
+ clm = self._clm
+ clm.findLogs()
+ clm.moveChatlogs()
+ content = os.listdir(self._chatdest)
+ self.failUnlessEqual(len(content), 1, content)
+ length = len("chatlog_20070129_0304_2302.txt")
+ c = content[0]
+ self.failUnless(c.startswith("chatlog_"))
+ self.failUnless(c.endswith(".txt"))
+ self.failUnlessEqual(len(c), length, c)
+
+ def tearDown(self):
+ shutil.rmtree(self._tmpdir)
+
def test_suite():
return unittest.TestSuite((
+ unittest.makeSuite(PlasmaChatTest),
DocTestSuite('moul.file.plasmalog')
))
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <ti...@us...> - 2007-01-29 18:46:36
|
Revision: 98
http://pymoul.svn.sourceforge.net/pymoul/?rev=98&view=rev
Author: tiran
Date: 2007-01-29 10:46:30 -0800 (Mon, 29 Jan 2007)
Log Message:
-----------
Some work on chatlogs and plasma logs
Modified Paths:
--------------
pymoul/trunk/setup_win32.py
pymoul/trunk/src/moul/file/chatlog.py
pymoul/trunk/src/moul/file/plasmalog.py
Modified: pymoul/trunk/setup_win32.py
===================================================================
--- pymoul/trunk/setup_win32.py 2007-01-29 13:15:59 UTC (rev 97)
+++ pymoul/trunk/setup_win32.py 2007-01-29 18:46:30 UTC (rev 98)
@@ -78,8 +78,8 @@
pexe['upx_args'] = '--mono --best'
# InnoSetup
pexe['innosetup'] = os.environ.get('INNOSETUP') # TODO:
+ pexe['inno_templates'] = "template.iss"
pexe['app_name'] = 'pyMoul'
- # not required at the moment
pexe['includes'].extend(findPyTz())
kw['zipfile'] = 'library.zip'
Modified: pymoul/trunk/src/moul/file/chatlog.py
===================================================================
--- pymoul/trunk/src/moul/file/chatlog.py 2007-01-29 13:15:59 UTC (rev 97)
+++ pymoul/trunk/src/moul/file/chatlog.py 2007-01-29 18:46:30 UTC (rev 98)
@@ -16,6 +16,17 @@
# Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
"""Chat log parser
+
+Chatlog format
+==============
+
+(MM/DD hh:mm:ss) Chat.log started...
+(MM/DD hh:mm:ss) ...Chat.log stopped.
+(MM/DD hh:mm:ss) From USER in LOCATION: msg
+(MM/DD hh:mm:ss) Error: ERRORMSG
+(MM/DD hh:mm:ss) USER: TEXT (note the two spaces!)
+(MM/DD hh:mm:ss) To USER: TEXT
+(MM/DD hh:mm:ss) USER action
"""
__author__ = "Christian Heimes"
__version__ = "$Id$"
@@ -23,22 +34,127 @@
import os
import re
-from glob import glob
+from fnmatch import fnmatch
+from stat import ST_MTIME
+from shutil import move
+from time import localtime
-CHAT_RE_TXT = r"^\((?P<M>\d{1,2})/(?P<D>\d{1,2})\ " \
- r"(?P<h>\d{1,2}):(?P<m>\d\d{1,2}):(?P<s>\d{1,2})\)" \
- r"(?P<space>\ {1,2})(?P<text>.*)$"
-CHAT_RE = re.compile(CHAT_RE_TXT)
+from moul.log import getLogger
+CHAT_RE = re.compile(
+ r"^\((?P<M>\d{1,2})/(?P<D>\d{1,2})\ " # MM/DD
+ r"(?P<h>\d{1,2}):(?P<m>\d\d{1,2}):(?P<s>\d{1,2})\)" # hh:mm:ss
+ r"(?P<space>\ {1,2})(?P<msg>.*)$") # text
+CHAT_STARTED = "Chat.log started..."
+CHAT_STOPPED = "...Chat.log stopped."
+TEXT_MSGFROM = re.compile(
+ r"From (?P<user>.*) in (?P<location>.*): (?P<msg>.*)"
+ # From USER in LOCATION: msg
+ )
+TEXT_MSGTO = re.compile(
+ r"To (?P<user>.*): (?P<msg>.*)"
+ # From USER in LOCATION: msg
+ )
+TEXT_ERROR = re.compile(
+ r"Error: (?P<msg>.*)"
+ # Error: message
+ )
+TEXT = re.compile(
+ r"(?P<user>.*): (?P<msg>.*)"
+ # User: message
+ )
+
+
+LOG = getLogger('moul.chat')
+
+def modtime(pathname):
+ """Modification time
+ """
+ return os.stat(pathname)[ST_MTIME]
+
class ChatlogMover(object):
"""
"""
+ _pat = "chat*.log"
+ _filename = "chatlog_%(sY)i%(sM)i%(sD)i_%(ch)i%(cm)i_%(sh)i%(sm)i.txt"
- def __init__(self, path, dest):
- self._path = path
- self._dest = dest
+ def __init__(self, srcdir, destdir):
+ self._path = srcdir
+ self._dest = destdir
self._logs = []
+ if not os.path.isdir(srcdir):
+ LOG.critical("%s is not a directory" % srcdir)
+ if not os.path.isdir(destdir):
+ LOG.info("Creating chatlog directory %s" % destdir)
+ os.mkdir(dest)
def findLogs(self):
- self._logs.append(os.path.join(self._path, 'chat*.log'))
+ """Find log files in self._path
+ Also calls and stores _findCreated(), modtime() and _makeFile()
+ for the file.
+ """
+ for file in os.listdir(self._path):
+ if not fnmatch(file, self._pat):
+ continue
+
+ fpath = os.path.join(self._path, file)
+ if not os.path.isfile(fpath):
+ continue
+ LOG.debug("Found chatlog %s" % fpath)
+ fd = open(fpath, 'r')
+ created = self._findCreated(fd)
+ if not created:
+ LOG.warning("Failed to parse chatlog %s" % fpath)
+ modtime = localtime(modtime(fpath))
+ newname = self._makeFilename(created, modtime)
+
+ details = {
+ 'fpath' : fpath,
+ 'filename' : file,
+ 'modtime' : localtime(modtime(fpath)),
+ 'created' : created,
+ 'newname' : newname,
+ 'newpath' : os.path.join(self._dest, newname),
+ }
+
+ self._logs.append(details)
+
+ def _findCreated(self, fd):
+ """Parse chatlog to find "started" date
+ """
+ created = None
+ while True:
+ line = fd.readline()
+ if not line:
+ break
+ mo = CHAT_RE.match(line)
+ if mo:
+ data = mo.groupdict()
+ if data['msg'].startswith(CHATLOG_STARTED):
+ created = (None, mo['M'], mo['D'], mo['h'], mo['m'],
+ mo['s'], None, None, None)
+ return created
+
+ def _makeFilename(self, created, stopped):
+ """Build a filename from created and stopped information
+ """
+ c, s = created, stopped
+ mapping = {
+ 'sY' : s['Y'], 'sM' : s['YM'], 'sD' : s['D'],
+ 'sh' : s['h'], 'sm' : s['m'], 'ss' : s['s'],
+ 'cM' : c['YM'], 'cD' : c['D'],
+ 'ch' : c['h'], 'cm' : c['m'], 'cs' : c['s'],
+ }
+ return self._filename % mapping
+
+ def moveChatlogs(self):
+ """Move chatlogs from old to new location and name
+ """
+ for details in self._logs:
+ old = details['fpath']
+ new = details['newpath']
+ if os.path.isfile(new):
+ LOG.warning("%s exists - overwriting" % new)
+ LOG.info("Move chatlog %s to %s" % (old, new))
+ move(old, new)
Modified: pymoul/trunk/src/moul/file/plasmalog.py
===================================================================
--- pymoul/trunk/src/moul/file/plasmalog.py 2007-01-29 13:15:59 UTC (rev 97)
+++ pymoul/trunk/src/moul/file/plasmalog.py 2007-01-29 18:46:30 UTC (rev 98)
@@ -25,76 +25,82 @@
from stat import ST_MTIME
import time
import zipfile
-import re
+from fnmatch import fnmatch
from moul.crypt.elf import decryptElf
PLASMA_LOG = "plasmalog.txt"
_marker = object()
-RE_SAFEEXT_TEXT = "\.(elf|txt|log|zip|jpg|jpeg)$"
-RE_SAFEXT = re.compile(RE_SAFEEXT_TEXT, re.IGNORECASE)
-def getTimeStamp(path):
- """Get time stamp yyyymmdd_hhmm based in the modification time
+class PlasmalogZipper(object):
+ """Zip plasma logs
"""
- sec = os.stat(path)[ST_MTIME]
- return time.strftime("%Y%m%d_%H%M", time.gmtime(sec))
+ _save_patterns = ['*.elf', '*.txt', '*.log', '*.zip', '*.jpg']
+
+ def __init__(self, srcdir, destdir):
+ self._srcdir = srcdir
+ self._destdir = destdir
-def isLogDir(path):
- """Check if a path is a valid plasma log directory
-
- Just checks for the plasmalog.txt file
-
- Returns either False or a time stamp
- """
- pl = os.path.join(path, PLASMA_LOG)
- if not os.path.isfile(pl):
- return False
- return getTimeStamp(pl)
-
-def zipLogDir(logdir, destdir, remove):
- """Zip all log files
-
- This function also zips subdirectories.
- """
- stored_dirs = []
-
- for root, dirs, files in os.walk(logdir):
- stamp = isLogDir(root)
- if not stamp:
- continue
- name = os.path.basename(root)
- zipname = "%s_%s.zip" % (name, stamp)
- zipfd = zipfile.ZipFile(os.path.join(destdir, zipname),
- 'w', zipfile.ZIP_DEFLATED)
- for file in files:
- if file.lower().startswith('chat.'):
- # omit chatlogs from the logs
+ def getTimeStamp(self, path):
+ """Get time stamp yyyymmdd_hhmm based in the modification time
+ """
+ sec = os.stat(path)[ST_MTIME]
+ return time.strftime("%Y%m%d_%H%M", time.localtime(sec))
+
+ def isLogDir(self, path):
+ """Check if a path is a valid plasma log directory
+
+ Just checks for the plasmalog.txt file
+
+ Returns either False or a time stamp
+ """
+ pl = os.path.join(path, PLASMA_LOG)
+ if not os.path.isfile(pl):
+ return False
+ return getTimeStamp(pl)
+
+ def zipLogDir(self):
+ """Zip all log files
+
+ This function also zips subdirectories.
+ """
+ stored_dirs = []
+
+ for root, dirs, files in os.walk(self._srcdir):
+ stamp = isLogDir(root)
+ if not stamp:
continue
- fname = os.path.join(root, file)
- arcname = os.path.join(name, file)
- zipfd.write(fname, arcname)
- #zipfd.printdir()
- zipfd.close()
- stored_dirs.append((root, zipname))
+ name = os.path.basename(root)
+ zipname = "%s_%s.zip" % (name, stamp)
+ zipfd = zipfile.ZipFile(os.path.join(self._destdir, zipname),
+ 'w', zipfile.ZIP_DEFLATED)
+ for file in files:
+ if file.lower().startswith('chat.'):
+ # omit chatlogs from the logs
+ continue
+ fname = os.path.join(root, file)
+ arcname = os.path.join(name, file)
+ zipfd.write(fname, arcname)
+ #zipfd.printdir()
+ zipfd.close()
+ stored_dirs.append((root, zipname))
- if remove:
- removeLogs(logdir)
+ return stored_dirs
- return stored_dirs
+ def removeLogs(self, logdir):
+ """Removes log directories
+
+ The removeLogs function removes only files considered as safe
+ """
+ for root, dirs, files in os.walk(logdir, topdown=False):
+ for name in files:
+ matches = [pat for pat in self._save_patterns
+ if fnmatch(basename, pat)]
+ if match:
+ os.remove(os.path.join(root, name))
+ else:
+ LOG.warning("Won't remove %s from %s" % (name, root))
+ for name in dirs:
+ os.rmdir(os.path.join(root, name))
-def removeLogs(logdir):
- """Removes log directories
-
- The removeLogs function removes only files considered as safe
- """
- for root, dirs, files in os.walk(logdir, topdown=False):
- for name in files:
- if RE_SAFEXT.search(name):
- os.remove(os.path.join(root, name))
- else:
- print name # XXX
- for name in dirs:
- os.rmdir(os.path.join(root, name))
-
- os.rmdir(logdir)
+ os.rmdir(logdir)
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <ti...@us...> - 2007-01-29 13:16:05
|
Revision: 97
http://pymoul.svn.sourceforge.net/pymoul/?rev=97&view=rev
Author: tiran
Date: 2007-01-29 05:15:59 -0800 (Mon, 29 Jan 2007)
Log Message:
-----------
Added iss template
Modified Paths:
--------------
pymoul/trunk/distutils_iss.py
Added Paths:
-----------
pymoul/trunk/template.iss
Modified: pymoul/trunk/distutils_iss.py
===================================================================
--- pymoul/trunk/distutils_iss.py 2007-01-29 12:59:51 UTC (rev 96)
+++ pymoul/trunk/distutils_iss.py 2007-01-29 13:15:59 UTC (rev 97)
@@ -13,6 +13,7 @@
from ConfigParser import SafeConfigParser
from ConfigParser import NoSectionError
from ConfigParser import DEFAULTSECT
+from string import ascii_letters
class ISSConfigParser(SafeConfigParser):
"""Config parser with some extensions for ISS
@@ -389,6 +390,9 @@
ip = interpolation.copy()
ip['appname'] = appname
ip['version'] = version
+ ip['appnamestripped'] = "".join([c for c in appname
+ if c in ascii_letters])
+ ip['appexe'] = self.windows_exe_files[0]
self.interpolation = ip
self.cfg = ISSConfigParser(ip)
@@ -425,7 +429,7 @@
self._writeLanguagesSect()
self._writeWindowsExeFiles()
self._writeLibFiles()
- self._writeIcons()
+ #self._writeIcons()
self._writeSections()
def _writeLanguagesSect(self):
Added: pymoul/trunk/template.iss
===================================================================
--- pymoul/trunk/template.iss (rev 0)
+++ pymoul/trunk/template.iss 2007-01-29 13:15:59 UTC (rev 97)
@@ -0,0 +1,40 @@
+; Script generated by the Inno Setup Script Wizard.
+; SEE THE DOCUMENTATION FOR DETAILS ON CREATING INNO SETUP SCRIPT FILES!
+
+[Setup]
+AppName=%(appname)s
+AppVerName=%(appname)s %(version)s
+AppPublisher=Christian Heimes
+AppPublisherURL=http://www.cheimes.de/
+AppSupportURL=http://pymoul.sourceforge.net/
+AppUpdatesURL=http://sourceforge.net/projects/pymoul/
+DefaultDirName={pf}\%(appname)s
+DefaultGroupName=%(appname)s
+LicenseFile=GPL.txt
+InfoBeforeFile=README.txt
+;InfoAfterFile=c:\Programme\Inno Setup 5\license.txt
+OutputDir=dist\
+OutputBaseFilename=setup_%(appnamestripped)s_%(version)s
+Compression=lzma
+SolidCompression=yes
+
+[Languages]
+Name: "english"; MessagesFile: "compiler:Default.isl"
+Name: "dutch"; MessagesFile: "compiler:Languages\Dutch.isl"
+Name: "french"; MessagesFile: "compiler:Languages\French.isl"
+Name: "german"; MessagesFile: "compiler:Languages\German.isl"
+Name: "italian"; MessagesFile: "compiler:Languages\Italian.isl"
+Name: "spanish"; MessagesFile: "compiler:Languages\Spanish.isl"
+
+[Tasks]
+Name: "desktopicon"; Description: "{cm:CreateDesktopIcon}"; GroupDescription: "{cm:AdditionalIcons}"; Flags: unchecked
+Name: "quicklaunchicon"; Description: "{cm:CreateQuickLaunchIcon}"; GroupDescription: "{cm:AdditionalIcons}"; Flags: unchecked
+
+[Icons]
+Name: "{group}\%(appname)s"; Filename: "{app}\%(appexe)s"
+Name: "{group}\{cm:ProgramOnTheWeb,%(appname)s}"; Filename: "http://pymoul.sourceforge.net/"
+Name: "{group}\{cm:UninstallProgram,%(appname)s}"; Filename: "{uninstallexe}"
+Name: "{userappdata}\Microsoft\Internet Explorer\Quick Launch\%(appname)s"; Filename: "{app}\%(appexe)"; Tasks: quicklaunchicon
+
+[Run]
+Filename: "{app}%(appexe)s"; Description: "{cm:LaunchProgram,My Program}"; Flags: nowait postinstall skipifsilent
Property changes on: pymoul/trunk/template.iss
___________________________________________________________________
Name: svn:eol-style
+ native
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <ti...@us...> - 2007-01-29 12:59:57
|
Revision: 96
http://pymoul.svn.sourceforge.net/pymoul/?rev=96&view=rev
Author: tiran
Date: 2007-01-29 04:59:51 -0800 (Mon, 29 Jan 2007)
Log Message:
-----------
Better InnoScript integration
Modified Paths:
--------------
pymoul/trunk/distutils_upx.py
Added Paths:
-----------
pymoul/trunk/distutils_iss.py
Copied: pymoul/trunk/distutils_iss.py (from rev 95, pymoul/trunk/distutils_upx.py)
===================================================================
--- pymoul/trunk/distutils_iss.py (rev 0)
+++ pymoul/trunk/distutils_iss.py 2007-01-29 12:59:51 UTC (rev 96)
@@ -0,0 +1,510 @@
+"""Distutils helper for creating and running InnoSetup Script files
+"""
+__author__ = "Christian Heimes"
+__version__ = "$Id"
+__revision__ = "$Revision$"
+
+import os
+import sys
+import re
+from distutils import log
+from fnmatch import fnmatch
+from subprocess import call as subcall
+from ConfigParser import SafeConfigParser
+from ConfigParser import NoSectionError
+from ConfigParser import DEFAULTSECT
+
+class ISSConfigParser(SafeConfigParser):
+ """Config parser with some extensions for ISS
+
+ new methods:
+ add_header(string) - Adds comments to the header
+ set_raw(section, string) - Adds a raw entry to a section
+ add_sectionif(section)
+ setif(section, option, value)
+
+ changed behavior:
+ doesn't write [default] section to file
+ interpolates "%(...)s" when writing to file
+ doesn't parse key: value
+ parses "Key: "value"; ..." to raw
+ writes sections in the order they are created
+
+ >>> from StringIO import StringIO
+ >>> defaults = {'appname' : 'Test App'}
+ >>> cfg = ISSConfigParser(defaults)
+ >>> cfg.add_header("header")
+
+ >>> cfg.add_section("testsection")
+ >>> cfg.set("testsection", "key", "value %(appname)s")
+ >>> cfg.set_raw("testsection", 'Rawline: "%(appname)s";')
+
+ >>> out = StringIO()
+ >>> cfg.write(out)
+ >>> out.seek(0)
+ >>> data = out.read()
+ >>> print data
+ ; header
+ [testsection]
+ key = value Test App
+ Rawline: "Test App";
+ <BLANKLINE>
+
+ >>> template = StringIO(data)
+ >>> del cfg, out, data
+ >>> cfg = ISSConfigParser(defaults)
+ >>> cfg.readfp(template)
+ >>> cfg._sections
+ {'testsection': {'__name__': 'testsection', 'key': 'value Test App'}}
+ >>> cfg._raw
+ {'testsection': ['Rawline: "Test App";']}
+
+ >>> out = StringIO()
+ >>> cfg.write(out)
+ >>> out.seek(0)
+ >>> data = out.read()
+ >>> print data
+ [testsection]
+ key = value Test App
+ Rawline: "Test App";
+ <BLANKLINE>
+
+ >>>
+ """
+ def __init__(self, defaults=None):
+ SafeConfigParser.__init__(self, defaults)
+ self._raw = {}
+ self._header = []
+ self._order = []
+
+ def add_header(self, value):
+ """Add a header comment
+ """
+ self._header.append(value)
+
+ def add_section(self, section):
+ """Create a new section in the configuration.
+ """
+ SafeConfigParser.add_section(self, section)
+ self._raw[section]= []
+ self._order.append(section)
+
+ def add_sectionif(self, section):
+ """Create a new section in the configuration if section doesn't exist.
+ """
+ if not self.has_section(section):
+ self.add_section(section)
+ return True
+
+ def setif(self, section, option, value):
+ """Set section-option to value if option is not yet set
+ """
+ if not self.has_option(section, option):
+ self.set(section, option, value)
+ return True
+
+ def set_raw(self, section, raw):
+ """Add a raw string to a section
+ """
+ try:
+ sec = self._raw[section]
+ except KeyError:
+ raise NoSectionError(section)
+ if isinstance(raw, (tuple, list)):
+ for r in raw:
+ sec.append(r)
+ else:
+ sec.append(raw)
+
+ def get_raw(self, section, raw=False, vars=None):
+ """Get all raw lines as string for a given section.
+
+ Interpolates %(var)s vars
+ """
+ d = self._defaults.copy()
+ try:
+ d.update(self._sections[section])
+ except KeyError:
+ if section != DEFAULTSECT:
+ raise NoSectionError(section)
+ # Update with the entry specific variables
+ if vars:
+ for key, value in vars.items():
+ d[self.optionxform(key)] = value
+ try:
+ rawdata = "\n".join(self._raw[section])
+ except KeyError:
+ return None
+
+ if raw:
+ return rawdata
+ else:
+ return self._interpolate(section, "RAWDATA", rawdata, d)
+
+ def optionxform(self, optionstr):
+ return optionstr
+
+ def write(self, fp):
+ """Write an .ini-format representation of the configuration state."""
+ for header in self._header:
+ fp.write("; %s\n" % header.replace('\n', '; \n'))
+ #if self._defaults:
+ # fp.write("[%s]\n" % DEFAULTSECT)
+ # for (key, value) in self._defaults.items():
+ # fp.write("%s = %s\n" % (key, str(value).replace('\n', '\n\t')))
+ # fp.write("\n")
+ for section in self._order:
+ fp.write("[%s]\n" % section)
+ for key in self._sections[section]:
+ if key == "__name__":
+ continue
+ value = self.get(section, key, raw=False)
+ fp.write("%s = %s\n" %
+ (key, str(value).replace('\n', '\n\t')))
+ rawdata = self.get_raw(section, raw=False)
+ if rawdata:
+ fp.write(rawdata)
+ fp.write("\n")
+
+ def remove_section(self, section):
+ """Remove a file section."""
+ existed = RawConfigParser.remove_section(self, section)
+ if existed:
+ del self._raw[section]
+ return existed
+
+ OPTCRE = re.compile(
+ r'(?P<option>[^=\s][^=]*)' # very permissive!
+ r'\s*(?P<vi>[=])\s*' # any number of space/tab,
+ # followed by separator
+ # (either : or =), followed
+ # by any # space/tab
+ r'(?P<value>.*)$' # everything up to eol
+ )
+
+ RAWRE = re.compile(
+ r'^[A-Z][A-Za-z]*:\s?' # 'Name: '
+ r'".*";' # '"value ...";' and
+ )
+
+ def _read(self, fp, fpname):
+ """Parse a sectioned setup file.
+
+ From ConfigParser.RawConfigParser
+ """
+ cursect = None # None, or a dictionary
+ curraw = None
+ optname = None
+ lineno = 0
+ e = None # None, or an exception
+ while True:
+ line = fp.readline()
+ if not line:
+ break
+ lineno = lineno + 1
+ # comment or blank line?
+ if line.strip() == '' or line[0] in '#;':
+ continue
+ if line.split(None, 1)[0].lower() == 'rem' and line[0] in "rR":
+ # no leading whitespace
+ continue
+ # continuation line?
+ if line[0].isspace() and cursect is not None and optname:
+ value = line.strip()
+ if value:
+ cursect[optname] = "%s\n%s" % (cursect[optname], value)
+ # a section header or option header?
+ else:
+ # is it a section header?
+ mo = self.SECTCRE.match(line)
+ if mo:
+ sectname = mo.group('header')
+ if sectname in self._sections:
+ cursect = self._sections[sectname]
+ curraw = self._raw[sectname]
+ elif sectname == DEFAULTSECT:
+ cursect = self._defaults
+ else:
+ cursect = {'__name__': sectname}
+ curraw = [] # new
+ self._order.append(sectname) # new
+ self._sections[sectname] = cursect
+ self._raw[sectname] = curraw # new
+ # So sections can't start with a continuation line
+ optname = None
+ # no section header in the file?
+ elif cursect is None:
+ raise MissingSectionHeaderError(fpname, lineno, line)
+ # an option line?
+ else:
+ mo = self.OPTCRE.match(line)
+ if mo:
+ optname, vi, optval = mo.group('option', 'vi', 'value')
+ if vi in ('=', ':') and ';' in optval:
+ # ';' is a comment delimiter only if it follows
+ # a spacing character
+ pos = optval.find(';')
+ if pos != -1 and optval[pos-1].isspace():
+ optval = optval[:pos]
+ optval = optval.strip()
+ # allow empty values
+ if optval == '""':
+ optval = ''
+ optname = self.optionxform(optname.rstrip())
+ cursect[optname] = optval
+ else:
+ mo = self.RAWRE.match(line) # new
+ if mo:
+ # found a InnoSetup raw line
+ curraw.append(line.strip())
+ else:
+ # a non-fatal parsing error occurred. set up the
+ # exception but keep going. the exception will be
+ # raised at the end of the file and will contain a
+ # list of all bogus lines
+ if not e:
+ e = ParsingError(fpname)
+ e.append(lineno, repr(line))
+ # if any parsing errors occurred, raise an exception
+ if e:
+ raise e
+
+
+class InnoSetupCommandMixin:
+ """Mixin class class for a distutils command
+
+ You have call initialize_options() and run() from your class!
+
+ >>> from tempfile import mkstemp
+ >>> tmphdlr, tmpfile = mkstemp()
+
+ >>> test = InnoSetupCommandMixin()
+ >>> test.initialize_options()
+ >>> test.app_name = "Test App"
+ >>> test.innosetup = True
+ >>> test.inno_script = tmpfile
+ >>> test.lib_dir = 'li',
+ >>> test.dist_dir = 'dist'
+ >>> test.windows_exe_files = [r'dist\\test.exe']
+ >>> test.lib_files = [r'dist\\lib1', r'dist\\lib2']
+
+ >>> try:
+ ... test.run()
+ ... finally:
+ ... data = open(tmpfile).read()
+ ... os.unlink(tmpfile)
+
+ #>>> print data
+ """
+ def initialize_options(self):
+ self.app_name = ''
+ self.innosetup = False
+ self.inno_script = None
+ self.inno_version = "1.0"
+ self.inno_templates = None
+ self.inno_interpolation = {}
+ self.inno_sections = {}
+ self.inno_languages = [('nl', 'Dutch'), ('de', 'German'),
+ ('fr', 'French'), ('it', 'Italian'),
+ ('es', 'Spanish')
+ ]
+
+ def run(self):
+ self._createInnoSetup()
+
+ def _createInnoSetup(self):
+ if not self.innosetup:
+ return
+
+ self._inno_script = InnoScript(
+ self.app_name,
+ self.lib_dir,
+ self.dist_dir,
+ self.windows_exe_files,
+ self.lib_files,
+ inno_script = self.inno_script,
+ templates = self.inno_templates,
+ interpolation = self.inno_interpolation,
+ sections = self.inno_sections,
+ languages = self.inno_languages)
+
+ print "*** creating the inno setup script***"
+ self._inno_script.create()
+ print "*** compiling the inno setup script***"
+ try:
+ self._inno_script.compile()
+ except RuntimeError, msg:
+ print "Failed to create installer:\n%s" % msg
+ # Note: By default the final setup.exe will be in an Output subdirectory.
+
+class InnoScript:
+ """Based on py2exe/samples/extending/setup.py
+
+ Requires http://www.jrsoftware.org
+
+ appname - name of the app
+ lib_dir - internal
+ dist_dir - internal
+ windows_exe_files - internal
+ lib_files - internal
+ isscript=None - path to IS script output file
+ templates = None - list of template file names or single file
+ version = "1.0" - version string
+ interpolation - dict with additional %()s interpolation items
+ sections - dict with additional section informations
+ languages - list with languages tuples e.g. [('de', 'German')]
+
+ sections = {'sectioname' :
+ {'key' : 'value',
+ 'RAW' : 'string or list with raw items'
+ }
+ }
+
+ """
+ def __init__(self,
+ appname,
+ lib_dir,
+ dist_dir,
+ windows_exe_files,
+ lib_files,
+ inno_script=None,
+ templates = None,
+ version = "1.0",
+ interpolation = {},
+ sections = {},
+ languages = []
+ ):
+ self.lib_dir = lib_dir
+ self.dist_dir = dist_dir
+ if not self.dist_dir[-1] in "\\/":
+ self.dist_dir += "\\"
+ self.windows_exe_files = [self.chop(p) for p in windows_exe_files]
+ self.lib_files = [self.chop(p) for p in lib_files]
+ if inno_script is None:
+ self.inno_script = os.path.join(dist_dir, appname.replace(' ', '_')+'.iss')
+ else:
+ self.inno_script = inno_script
+ self.fd = open(self.inno_script, "w")
+
+ ip = interpolation.copy()
+ ip['appname'] = appname
+ ip['version'] = version
+ self.interpolation = ip
+
+ self.cfg = ISSConfigParser(ip)
+ if templates:
+ read = self.cfg.read(templates)
+ self.sections = sections
+ self.languages = languages
+
+ def chop(self, pathname):
+ assert pathname.startswith(self.dist_dir)
+ return pathname[len(self.dist_dir):]
+
+ def create(self):
+ """create Inno Script
+ """
+ self.createInnoScript()
+ self.modifyInnoScript()
+ self.writeInnoScript()
+
+ def createInnoScript(self):
+ """Create Inno Script cfg
+ """
+ cfg = self.cfg
+ cfg.add_header("WARNING: This script has been created by py2exe. Changes to this script")
+ cfg.add_header("will be overwritten the next time py2exe is run!\n")
+
+ cfg.add_sectionif("Setup")
+ # Setup
+ cfg.setif("Setup", "AppName", "%(appname)s")
+ cfg.setif("Setup", "AppVerName", "%(appname)s %(version)s")
+ cfg.setif("Setup", "DefaultDirName", "{pf}\%(appname)s")
+ cfg.setif("Setup", "DefaultGroupName", "%(appname)s")
+
+ self._writeLanguagesSect()
+ self._writeWindowsExeFiles()
+ self._writeLibFiles()
+ self._writeIcons()
+ self._writeSections()
+
+ def _writeLanguagesSect(self):
+ cfg = self.cfg
+ if not self.languages:
+ return
+ cfg.add_sectionif('Languages')
+ for key, lang in self.languages:
+ cfg.set_raw("Languages",
+ 'Name: "%s"; MessagesFile: "compiler:Languages\%s.isl"' %
+ (key, lang))
+
+ def _writeWindowsExeFiles(self):
+ cfg = self.cfg
+ cfg.add_sectionif("Files")
+ for path in self.windows_exe_files:
+ cfg.set_raw("Files",
+ r'Source: "%s"; DestDir: "{app}\%s"; Flags: ignoreversion'
+ % (path, os.path.dirname(path)) )
+
+ def _writeLibFiles(self):
+ cfg = self.cfg
+ cfg.add_sectionif("Files")
+ for path in self.lib_files:
+ cfg.set_raw("Files",
+ r'Source: "%s"; DestDir: "{app}\%s"; Flags: ignoreversion'
+ % (path, os.path.dirname(path)) )
+
+ def _writeIcons(self):
+ cfg = self.cfg
+ cfg.add_sectionif("Icons")
+ for path in self.windows_exe_files:
+ cfg.set_raw("Icons",
+ 'Name: "{group}\\%(appname)s"; Filename: "{app}\\' + path + '"')
+ cfg.set_raw("Icons", r'Name: "{group}\Uninstall %(appname)s"; Filename: "{uninstallexe}"')
+
+ def _writeSections(self):
+ cfg = self.cfg
+ # Additional things in self.sections
+ for section in self.sections:
+ cfg.add_sectionif(section)
+ for key, value in self.sections[section].items():
+ if key == "RAW":
+ cfg.set_raw(section, value)
+ else:
+ cfg.set(section, key, value)
+
+ def modifyInnoScript(self):
+ """Hook
+ """
+ pass
+
+ def writeInnoScript(self):
+ """Write script to disk
+ """
+ self.cfg.write(self.fd)
+ self.fd.close()
+
+ def compile(self):
+ import ctypes
+ res = ctypes.windll.shell32.ShellExecuteA(0, "compile",
+ self.isscript,
+ None,
+ None,
+ 0)
+ if res < 32:
+ raise RuntimeError("ShellExecute failed, error %d" % res)
+
+ def __call__(self):
+ self.create()
+ self.compile()
+
+def test_suite():
+ import unittest
+ from doctest import DocTestSuite
+ return unittest.TestSuite((
+ DocTestSuite(__name__),
+ ))
+
+if __name__ == '__main__':
+ import unittest
+ unittest.main(defaultTest="test_suite")
Modified: pymoul/trunk/distutils_upx.py
===================================================================
--- pymoul/trunk/distutils_upx.py 2007-01-28 23:51:53 UTC (rev 95)
+++ pymoul/trunk/distutils_upx.py 2007-01-29 12:59:51 UTC (rev 96)
@@ -12,9 +12,9 @@
from distutils import log
from stat import ST_SIZE
from fnmatch import fnmatch
-from ConfigParser import RawConfigParser
+from distutils_iss import InnoSetupCommandMixin
-class UpxCommand:
+class UpxCommand(InnoSetupCommandMixin):
"""Upx packer mixin class for distutils
Usage:
@@ -36,6 +36,7 @@
def initialize_options(self):
result = self._otherclass().initialize_options(self)
+ InnoSetupCommandMixin.initialize_options(self)
self.upx = True
self.upx_args = '--no-color'
self.upx_path = 'upx'
@@ -45,10 +46,6 @@
'dylib', # Mac OS X
]
self.upx_ignore = []
-
- self.app_name = ''
- self.innosetup = False
-
return result
def finalize_options(self):
@@ -65,7 +62,7 @@
def run(self, *args, **kwargs):
result = self._otherclass().run(self, *args, **kwargs)
self._upxPack()
- self._createInnoSetup()
+ InnoSetupCommandMixin.run(self)
return result
def _upxPack(self):
@@ -94,13 +91,13 @@
matches = [pat for pat in self.upx_ignore if fnmatch(basename, pat)]
if matches:
continue
-
+
origsize = os.stat(fname)[ST_SIZE]
self._upxPackFile(os.path.normpath(fname))
newsize = os.stat(fname)[ST_SIZE]
ratio = newsize*100 / origsize
packed.append((basename, origsize, newsize, ratio))
-
+
print "\n*** UPX result ***"
for basename, origsize, newsize, ratio in packed:
print " %s packed to %i%%" % (basename, ratio)
@@ -147,186 +144,10 @@
Find next class in MRO that is not based on UpxCommand class
"""
for c in getmro(cls):
- if not issubclass(c, UpxCommand):
+ if not issubclass(c, (UpxCommand, InnoSetupCommandMixin)):
return c
raise ValueError(cls)
- def _createInnoSetup(self):
- if not self.innosetup:
- return
-
- script = InnoScript(self.app_name,
- self.lib_dir,
- self.dist_dir,
- self.windows_exe_files,
- self.lib_files)
- print "*** creating the inno setup script***"
- script.create()
- print "*** compiling the inno setup script***"
- try:
- script.compile()
- except RuntimeError, msg:
- print "Failed to create installer:\n%s" % msg
- # Note: By default the final setup.exe will be in an Output subdirectory.
-
-class InnoScript:
- """Based on py2exe/samples/extending/setup.py
-
- Requires http://www.jrsoftware.org
- """
- def __init__(self,
- name,
- lib_dir,
- dist_dir,
- windows_exe_files = [],
- lib_files = [],
- version = "1.0"):
- self.lib_dir = lib_dir
- self.dist_dir = dist_dir
- # TODO: better name mangling
- self.pathname = os.path.join(dist_dir, name.replace(' ', '_')+'.iss')
- self.cfg = ISSConfigParser()
- if not self.dist_dir[-1] in "\\/":
- self.dist_dir += "\\"
- self.name = name
- self.version = version
- self.windows_exe_files = [self.chop(p) for p in windows_exe_files]
- self.lib_files = [self.chop(p) for p in lib_files]
- self.setup_kwargs = {
- }
- self.languages = ["dutch", "french", "german", "italian", "spanish"]
-
- def chop(self, pathname):
- assert pathname.startswith(self.dist_dir)
- return pathname[len(self.dist_dir):]
-
- def create(self):
- fd = self.file = open(self.pathname, "w")
- cfg = self.cfg
- cfg.add_header("; WARNING: This script has been created by py2exe. Changes to this script")
- cfg.add_header("; will be overwritten the next time py2exe is run!\n")
- cfg.add_section('Setup')
- cfg.add_section('Files')
- cfg.add_section('Icons')
- cfg.add_section('Languages')
- cfg.add_section('Tasks')
- cfg.add_section('Run')
-
- # Setup
- cfg.set("Setup", "AppName", self.name)
- cfg.set("Setup", "AppVerName", "%s %s" % (self.name, self.version))
- cfg.set("Setup", "DefaultDirName", "{pf}\%s" % self.name)
- cfg.set("Setup", "DefaultGroupName", self.name)
- for key, value in self.setup_kwargs.items():
- cfg.set("Setup", key, value)
- # Languages
- cfg.set_raw('Languages',
- 'Name: "english"; MessagesFile: "compiler:Default.isl"')
- for lang in self.languages:
- cfg.set_raw("Languages",
- 'Name: "%s"; MessagesFile: "compiler:Languages/%s.isl"'
- % (lang, lang.capitalize()))
-
- for path in self.windows_exe_files + self.lib_files:
- cfg.set_raw("Files",
- r'Source: "%s"; DestDir: "{app}\%s"; Flags: ignoreversion'
- % (path, os.path.dirname(path))
- )
- for path in self.windows_exe_files:
- cfg.set_raw("Icons",
- 'Name: "{group}\%s"; Filename: "{app}\%s"' %
- (self.name, path)
- )
- cfg.set_raw("Icons", 'Name: "{group}\Uninstall %s"; Filename: "{uninstallexe}"' % self.name)
-
- def compile(self):
- try:
- import ctypes
- except ImportError:
- try:
- import win32api
- except ImportError:
- import os
- os.startfile(self.pathname)
- else:
- #print "Ok, using win32api."
- win32api.ShellExecute(0, "compile",
- self.pathname,
- None,
- None,
- 0)
- else:
- #print "Cool, you have ctypes installed."
- res = ctypes.windll.shell32.ShellExecuteA(0, "compile",
- self.pathname,
- None,
- None,
- 0)
- if res < 32:
- raise RuntimeError("ShellExecute failed, error %d" % res)
-
-class ISSConfigParser(RawConfigParser):
- """Config parser for InnoSetupScripts
-
- Supports *only* writing and no parsing!
- """
- def __init__(self, defaults=None):
- RawConfigParser__init__(self, defaults)
- self._raw = {}
- self._header = []
-
- def add_header(self, value):
- """Add a header comment
- """
- self._header.append(value)
-
- def add_section(self, section):
- """Create a new section in the configuration.
- """
- RawConfigParser.add_section(self, section)
- self._raw[section]= []
-
- def set_raw(self, section, raw):
- """Add a raw string to a section
-
- TODO: use NoSectionError
- """
- self._raw[section] = raw
-
- def _read(self, fp, fpname):
- """Read and parse a filename or a list of filenames.
- """
- raise NotImplementedError
-
- def optionxform(self, optionstr):
- return optionstr
-
- def write(self, fp):
- """Write an .ini-format representation of the configuration state."""
- for header in self._headers:
- fp.write("; %s\n" % header.replace('\n', '; \n'))
- if self._defaults:
- fp.write("[%s]\n" % DEFAULTSECT)
- for (key, value) in self._defaults.items():
- fp.write("%s = %s\n" % (key, str(value).replace('\n', '\n\t')))
- fp.write("\n")
- for section in self._sections:
- fp.write("[%s]\n" % section)
- for (key, value) in self._sections[section].items():
- if key != "__name__":
- fp.write("%s = %s\n" %
- (key, str(value).replace('\n', '\n\t')))
- for raw in self._raw['section']:
- fp.write(str(raw).replace('\n', '\n\t') +'\n')
- fp.write("\n")
-
- def remove_section(self, section):
- """Remove a file section."""
- existed = RawConfigParser.remove_section(self, section)
- if existed:
- del self._raw[section]
- return existed
-
try:
from py2exe.build_exe import py2exe
except ImportError:
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <ti...@us...> - 2007-01-28 23:51:55
|
Revision: 95
http://pymoul.svn.sourceforge.net/pymoul/?rev=95&view=rev
Author: tiran
Date: 2007-01-28 15:51:53 -0800 (Sun, 28 Jan 2007)
Log Message:
-----------
Enhanced supported for IS script
Modified Paths:
--------------
pymoul/trunk/Makefile.in
pymoul/trunk/distutils_upx.py
Added Paths:
-----------
pymoul/trunk/src/moul/qt/i18n/pymoul_nl.qm
pymoul/trunk/src/moul/qt/i18n/pymoul_nl.ts
Modified: pymoul/trunk/Makefile.in
===================================================================
--- pymoul/trunk/Makefile.in 2007-01-28 21:14:23 UTC (rev 94)
+++ pymoul/trunk/Makefile.in 2007-01-28 23:51:53 UTC (rev 95)
@@ -6,7 +6,7 @@
FINDQT=find src/moul/qt \( -name '*.py' -o -name '*.ui' \) $(NOTSVN)
FINDTEXT=find src/moul \( -name '*.py' -o -name '*.txt' -o -name '*.qrc' -o -name '*.ui' -o -name '*.ts' \) $(NOTSVN)
FINDHASH= find . -not \( -name '*.txt' -o -name '*.asc' \) -a -not -type d
-LANGS=de fr it es
+LANGS=de es fr it nl
TESTFLAGS=-v
TESTOPTS=
SETUPFLAGS=
Modified: pymoul/trunk/distutils_upx.py
===================================================================
--- pymoul/trunk/distutils_upx.py 2007-01-28 21:14:23 UTC (rev 94)
+++ pymoul/trunk/distutils_upx.py 2007-01-28 23:51:53 UTC (rev 95)
@@ -12,6 +12,7 @@
from distutils import log
from stat import ST_SIZE
from fnmatch import fnmatch
+from ConfigParser import RawConfigParser
class UpxCommand:
"""Upx packer mixin class for distutils
@@ -184,38 +185,59 @@
self.dist_dir = dist_dir
# TODO: better name mangling
self.pathname = os.path.join(dist_dir, name.replace(' ', '_')+'.iss')
+ self.cfg = ISSConfigParser()
if not self.dist_dir[-1] in "\\/":
self.dist_dir += "\\"
self.name = name
self.version = version
self.windows_exe_files = [self.chop(p) for p in windows_exe_files]
self.lib_files = [self.chop(p) for p in lib_files]
+ self.setup_kwargs = {
+ }
+ self.languages = ["dutch", "french", "german", "italian", "spanish"]
def chop(self, pathname):
assert pathname.startswith(self.dist_dir)
return pathname[len(self.dist_dir):]
def create(self):
- ofi = self.file = open(self.pathname, "w")
- print >> ofi, "; WARNING: This script has been created by py2exe. Changes to this script"
- print >> ofi, "; will be overwritten the next time py2exe is run!"
- print >> ofi, r"[Setup]"
- print >> ofi, r"AppName=%s" % self.name
- print >> ofi, r"AppVerName=%s %s" % (self.name, self.version)
- print >> ofi, r"DefaultDirName={pf}\%s" % self.name
- print >> ofi, r"DefaultGroupName=%s" % self.name
- print >> ofi
-
- print >> ofi, r"[Files]"
+ fd = self.file = open(self.pathname, "w")
+ cfg = self.cfg
+ cfg.add_header("; WARNING: This script has been created by py2exe. Changes to this script")
+ cfg.add_header("; will be overwritten the next time py2exe is run!\n")
+ cfg.add_section('Setup')
+ cfg.add_section('Files')
+ cfg.add_section('Icons')
+ cfg.add_section('Languages')
+ cfg.add_section('Tasks')
+ cfg.add_section('Run')
+
+ # Setup
+ cfg.set("Setup", "AppName", self.name)
+ cfg.set("Setup", "AppVerName", "%s %s" % (self.name, self.version))
+ cfg.set("Setup", "DefaultDirName", "{pf}\%s" % self.name)
+ cfg.set("Setup", "DefaultGroupName", self.name)
+ for key, value in self.setup_kwargs.items():
+ cfg.set("Setup", key, value)
+ # Languages
+ cfg.set_raw('Languages',
+ 'Name: "english"; MessagesFile: "compiler:Default.isl"')
+ for lang in self.languages:
+ cfg.set_raw("Languages",
+ 'Name: "%s"; MessagesFile: "compiler:Languages/%s.isl"'
+ % (lang, lang.capitalize()))
+
for path in self.windows_exe_files + self.lib_files:
- print >> ofi, r'Source: "%s"; DestDir: "{app}\%s"; Flags: ignoreversion' % (path, os.path.dirname(path))
- print >> ofi
-
- print >> ofi, r"[Icons]"
+ cfg.set_raw("Files",
+ r'Source: "%s"; DestDir: "{app}\%s"; Flags: ignoreversion'
+ % (path, os.path.dirname(path))
+ )
for path in self.windows_exe_files:
- print >> ofi, r'Name: "{group}\%s"; Filename: "{app}\%s"' % \
- (self.name, path)
- print >> ofi, 'Name: "{group}\Uninstall %s"; Filename: "{uninstallexe}"' % self.name
+ cfg.set_raw("Icons",
+ 'Name: "{group}\%s"; Filename: "{app}\%s"' %
+ (self.name, path)
+ )
+ cfg.set_raw("Icons", 'Name: "{group}\Uninstall %s"; Filename: "{uninstallexe}"' % self.name)
def compile(self):
try:
@@ -243,7 +265,68 @@
if res < 32:
raise RuntimeError("ShellExecute failed, error %d" % res)
+class ISSConfigParser(RawConfigParser):
+ """Config parser for InnoSetupScripts
+ Supports *only* writing and no parsing!
+ """
+ def __init__(self, defaults=None):
+ RawConfigParser__init__(self, defaults)
+ self._raw = {}
+ self._header = []
+
+ def add_header(self, value):
+ """Add a header comment
+ """
+ self._header.append(value)
+
+ def add_section(self, section):
+ """Create a new section in the configuration.
+ """
+ RawConfigParser.add_section(self, section)
+ self._raw[section]= []
+
+ def set_raw(self, section, raw):
+ """Add a raw string to a section
+
+ TODO: use NoSectionError
+ """
+ self._raw[section] = raw
+
+ def _read(self, fp, fpname):
+ """Read and parse a filename or a list of filenames.
+ """
+ raise NotImplementedError
+
+ def optionxform(self, optionstr):
+ return optionstr
+
+ def write(self, fp):
+ """Write an .ini-format representation of the configuration state."""
+ for header in self._headers:
+ fp.write("; %s\n" % header.replace('\n', '; \n'))
+ if self._defaults:
+ fp.write("[%s]\n" % DEFAULTSECT)
+ for (key, value) in self._defaults.items():
+ fp.write("%s = %s\n" % (key, str(value).replace('\n', '\n\t')))
+ fp.write("\n")
+ for section in self._sections:
+ fp.write("[%s]\n" % section)
+ for (key, value) in self._sections[section].items():
+ if key != "__name__":
+ fp.write("%s = %s\n" %
+ (key, str(value).replace('\n', '\n\t')))
+ for raw in self._raw['section']:
+ fp.write(str(raw).replace('\n', '\n\t') +'\n')
+ fp.write("\n")
+
+ def remove_section(self, section):
+ """Remove a file section."""
+ existed = RawConfigParser.remove_section(self, section)
+ if existed:
+ del self._raw[section]
+ return existed
+
try:
from py2exe.build_exe import py2exe
except ImportError:
Added: pymoul/trunk/src/moul/qt/i18n/pymoul_nl.qm
===================================================================
(Binary files differ)
Property changes on: pymoul/trunk/src/moul/qt/i18n/pymoul_nl.qm
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: pymoul/trunk/src/moul/qt/i18n/pymoul_nl.ts
===================================================================
--- pymoul/trunk/src/moul/qt/i18n/pymoul_nl.ts (rev 0)
+++ pymoul/trunk/src/moul/qt/i18n/pymoul_nl.ts 2007-01-28 23:51:53 UTC (rev 95)
@@ -0,0 +1,248 @@
+<!DOCTYPE TS><TS>
+<context>
+ <name>MainWindow</name>
+ <message>
+ <source>Tool for Myst Online</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Configure</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Windowed</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Vertical Sync</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Display Shadows</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Screen Resolution</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>800x600 (4:3)</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Quality</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Texture Quality</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Low</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>High</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Anti-Aliasing</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Graphics Quality</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Med.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Ultra</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Shadow Quality</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Anisotropic-Filtering</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Graphics</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Level</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>NPC Voices</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Sound FX</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Ambience Sound</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Music</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Mute all</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Hardware</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Sound Priority</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Audio Modes</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Generic Software</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Enable EAX</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Voice chat</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Microphon Level</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Enable Voice Chat</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Audio</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Time zones</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Cavern time:</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Cyan time:</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>UTC -0</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>(Mountain Standard Time)</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>(Pacific Standard Time)</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>D'ni time</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Time</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Ping servers</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Ping</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source><html><head><meta name="qrichtext" content="1" /><style type="text/css">
+p, li { white-space: pre-wrap; }
+</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal; text-decoration:none;">
+<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p></body></html></source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Servers</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Browse in game documents</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Age</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Element</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Language</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Set</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Documents</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>pyMoul tools</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>About</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>MOUL is running</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>MOUL</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>MOUL is not running</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Not Implemented</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Sorry, this feature is not implemented yet!</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Error opening graphics.ini</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Error opening audio.ini</source>
+ <translation type="unfinished"></translation>
+ </message>
+</context>
+</TS>
Property changes on: pymoul/trunk/src/moul/qt/i18n/pymoul_nl.ts
___________________________________________________________________
Name: svn:eol-style
+ native
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <ti...@us...> - 2007-01-28 21:14:22
|
Revision: 94
http://pymoul.svn.sourceforge.net/pymoul/?rev=94&view=rev
Author: tiran
Date: 2007-01-28 13:14:23 -0800 (Sun, 28 Jan 2007)
Log Message:
-----------
include more files in dist
Added hash stuff
Modified Paths:
--------------
pymoul/trunk/Makefile.in
pymoul/trunk/compileui.py
pymoul/trunk/setup.py
Modified: pymoul/trunk/Makefile.in
===================================================================
--- pymoul/trunk/Makefile.in 2007-01-28 17:15:47 UTC (rev 93)
+++ pymoul/trunk/Makefile.in 2007-01-28 21:14:23 UTC (rev 94)
@@ -4,7 +4,8 @@
FINDPYTXT=find src/moul \( -name '*.py' -o -name '*.txt' \) $(NOTSVN)
FINDPY=find src/moul -name '*.py' $(NOTSVN)
FINDQT=find src/moul/qt \( -name '*.py' -o -name '*.ui' \) $(NOTSVN)
-FINDTEXT=find src/moul \( -name '*.py' -o -name '*.txt' -o -name '*.qrc' -o -name '*.ui' -o -name '*.ts' \) $(NOTSVN)
+FINDTEXT=find src/moul \( -name '*.py' -o -name '*.txt' -o -name '*.qrc' -o -name '*.ui' -o -name '*.ts' \) $(NOTSVN)
+FINDHASH= find . -not \( -name '*.txt' -o -name '*.asc' \) -a -not -type d
LANGS=de fr it es
TESTFLAGS=-v
TESTOPTS=
@@ -78,3 +79,9 @@
lrelease src/moul/qt/i18n/pymoul_$${L}.ts; \
done
+hash:
+ cd dist && $(FINDHASH) | xargs md5sum >md5.txt
+ cd dist && $(FINDHASH) | xargs sha1sum >sha1.txt
+ cd dist && $(FINDHASH) | xargs gpg --detach-sign -a
+
+
Modified: pymoul/trunk/compileui.py
===================================================================
--- pymoul/trunk/compileui.py 2007-01-28 17:15:47 UTC (rev 93)
+++ pymoul/trunk/compileui.py 2007-01-28 21:14:23 UTC (rev 94)
@@ -11,7 +11,7 @@
from PyQt4 import uic
-RE_RC_TEXT = "^import\ (?P<module>[a-zA-Z]\w*_rc)\s$"
+RE_RC_TEXT = "^import[ \.\\/]*(?P<module>[a-zA-Z]\w*_rc)\s$"
RE_RC = re.compile(RE_RC_TEXT)
UI_EXT = '.ui'
@@ -19,7 +19,7 @@
QRC_EXT = '.qrc'
PY_QRC_EXT = '_rc.py'
QRC_COMPILER = "pyrcc4 -o %(py)s %(qrc)s"
-UI_MODULE = "moul.qt.ui"
+QRC_PACKAGE = "moul.qt.ui"
def _newer(orig, py):
try:
@@ -81,7 +81,7 @@
# faster than re
match = RE_RC.match(line)
if match:
- line = match.expand("from %s import \g<module>" % UI_MODULE)
+ line = match.expand("from %s import \g<module>" % QRC_PACKAGE)
lines.append(line)
fin.close()
fout = open(fname, 'w')
Modified: pymoul/trunk/setup.py
===================================================================
--- pymoul/trunk/setup.py 2007-01-28 17:15:47 UTC (rev 93)
+++ pymoul/trunk/setup.py 2007-01-28 21:14:23 UTC (rev 94)
@@ -58,7 +58,10 @@
setup_options = dict(
setup_requires = ["setuptools>="+SETUPTOOLS_VERSION,],
install_requires = [],
- data_files = list(glob('*.txt')),
+ data_files = [
+ ('docs', list(glob('*.txt'))),
+ ('i18', list(glob('src/moul/qt/i18n/pymoul_*.*'))),
+ ],
package_dir = {'' : 'src'},
packages = find_packages('src', exclude="moul.qt"),
include_package_data = True,
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <ti...@us...> - 2007-01-28 17:15:46
|
Revision: 93
http://pymoul.svn.sourceforge.net/pymoul/?rev=93&view=rev
Author: tiran
Date: 2007-01-28 09:15:47 -0800 (Sun, 28 Jan 2007)
Log Message:
-----------
Changed log level
Modified Paths:
--------------
pymoul/trunk/src/moul/file/wdysini.py
pymoul/trunk/src/moul/log.py
pymoul/trunk/src/moul/osdependent/__init__.py
pymoul/trunk/src/moul/qt/mainwindow.py
pymoul/trunk/src/moul/qt/ui/moulqt_rc.py
Modified: pymoul/trunk/src/moul/file/wdysini.py
===================================================================
--- pymoul/trunk/src/moul/file/wdysini.py 2007-01-28 16:43:16 UTC (rev 92)
+++ pymoul/trunk/src/moul/file/wdysini.py 2007-01-28 17:15:47 UTC (rev 93)
@@ -369,7 +369,7 @@
self.clear()
if isinstance(fd_name, basestring):
fd = open(fd_name, 'rb')
- LOG.debug("Parsing encrypted file %s" % fd_name)
+ LOG.info("Parsing encrypted file %s" % fd_name)
close = True
else:
fd = fd_name
@@ -514,7 +514,7 @@
# check for OpenAL device
name = self._get('Audio.SetDeviceName')
if name not in self._devices:
- LOG.debug("Device added: %s" % name)
+ LOG.info("Device added: %s" % name)
self._devices.append(name)
def getDeviceIdx(self, name):
Modified: pymoul/trunk/src/moul/log.py
===================================================================
--- pymoul/trunk/src/moul/log.py 2007-01-28 16:43:16 UTC (rev 92)
+++ pymoul/trunk/src/moul/log.py 2007-01-28 17:15:47 UTC (rev 93)
@@ -84,7 +84,7 @@
global fhdlr
from moul.config import getPyMoulDataDir
logFile = os.path.join(getPyMoulDataDir(check=True), 'pymoul.log')
- LOG.debug("Adding file logger: %s" % logFile)
+ LOG.info("Adding file logger: %s" % logFile)
fhdlr = handlers.RotatingFileHandler(logFile, backupCount=9)
fhdlr.setFormatter(format)
root.addHandler(fhdlr)
@@ -92,15 +92,15 @@
def _systemInfo():
from moul.osdependent import __INFO__
- LOG.debug("pyMoul version: %s" % moul_version)
- LOG.debug("Python: %s" % repr(sys.version_info))
- LOG.debug("Python: %s" % sys.version.replace('\n', ' '))
- LOG.debug("Platform: %s, OS name: %s" % (sys.platform, os.name))
- LOG.debug("system %r, node %r, release %r, version %r, machine %r, processor %r"
- % platform.uname())
- LOG.debug("platform name: %s" % platform.platform(True))
- LOG.debug("sys.frozen status: %s" % __FROZEN__)
- LOG.debug("OS detected: win32: %r, cygwin: %r, Linux: %r, Mac: %r, BSD: %r, "
+ LOG.info("pyMoul version: %s" % moul_version)
+ LOG.info("Python: %s" % repr(sys.version_info))
+ LOG.info("Python: %s" % sys.version.replace('\n', ' '))
+ LOG.info("Platform: %s, OS name: %s" % (sys.platform, os.name))
+ LOG.info("system %r, node %r, release %r, version %r, machine %r, processor %r"
+ % platform.uname())
+ LOG.info("platform name: %s" % platform.platform(True))
+ LOG.info("sys.frozen status: %s" % __FROZEN__)
+ LOG.info("OS detected: win32: %r, cygwin: %r, Linux: %r, Mac: %r, BSD: %r, "
"posix/Un*x: %r, NT: %r" % __INFO__)
# no setup the logging stuff!
Modified: pymoul/trunk/src/moul/osdependent/__init__.py
===================================================================
--- pymoul/trunk/src/moul/osdependent/__init__.py 2007-01-28 16:43:16 UTC (rev 92)
+++ pymoul/trunk/src/moul/osdependent/__init__.py 2007-01-28 17:15:47 UTC (rev 93)
@@ -142,7 +142,8 @@
raise ValueError("Datadir's parent dir does not exist: %s"
% par)
else:
- LOG.debug("Creating pyMoul data dir %s" % datadir)
+ LOG.info("Creating pyMoul data dir %s" % datadir)
os.mkdir(datadir, 0750)
- LOG.debug("Using pyMoul data dir %s" % datadir)
+ LOG.info("Using pyMoul data dir %s" % datadir)
return datadir
+
Modified: pymoul/trunk/src/moul/qt/mainwindow.py
===================================================================
--- pymoul/trunk/src/moul/qt/mainwindow.py 2007-01-28 16:43:16 UTC (rev 92)
+++ pymoul/trunk/src/moul/qt/mainwindow.py 2007-01-28 17:15:47 UTC (rev 93)
@@ -520,11 +520,11 @@
self.text_ping.insertPlainText("PING: %0.3f\n" % time)
def on_pingthread_dnserror(self, name, errcode, errmsg):
- LOG.debug('dns error: %s, %i, %s' % (name, errcode, errmsg))
+ LOG.error('dns error: %s, %i, %s' % (name, errcode, errmsg))
self.text_ping.insertPlainText("%s ... DNS error: %s\n" % (name, errmsg))
def on_pingthread_pingerror(self, name, errcode, errmsg):
- LOG.debug('ping error: %s, %i, %s' % (name, errcode, errmsg))
+ LOG.error('ping error: %s, %i, %s' % (name, errcode, errmsg))
self.text_ping.insertPlainText("PING error: %s\n" % errmsg)
@pyqtSignature("bool")
Modified: pymoul/trunk/src/moul/qt/ui/moulqt_rc.py
===================================================================
--- pymoul/trunk/src/moul/qt/ui/moulqt_rc.py 2007-01-28 16:43:16 UTC (rev 92)
+++ pymoul/trunk/src/moul/qt/ui/moulqt_rc.py 2007-01-28 17:15:47 UTC (rev 93)
@@ -2,8 +2,8 @@
# Resource object code
#
-# Created: Mi 17. Jan 17:01:45 2007
-# by: The Resource Compiler for PyQt (Qt v4.2.2)
+# Created: So Jan 28 18:10:39 2007
+# by: The Resource Compiler for PyQt (Qt v4.2.0)
#
# WARNING! All changes made in this file will be lost!
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <ti...@us...> - 2007-01-28 16:43:17
|
Revision: 92
http://pymoul.svn.sourceforge.net/pymoul/?rev=92&view=rev
Author: tiran
Date: 2007-01-28 08:43:16 -0800 (Sun, 28 Jan 2007)
Log Message:
-----------
Added translation files
Modified Paths:
--------------
pymoul/trunk/Makefile.in
pymoul/trunk/src/moul/osdependent/singleapp.py
pymoul/trunk/src/moul/qt/i18n/pymoul_de.ts
Added Paths:
-----------
pymoul/trunk/src/moul/qt/i18n/pymoul_de.qm
pymoul/trunk/src/moul/qt/i18n/pymoul_es.qm
pymoul/trunk/src/moul/qt/i18n/pymoul_es.ts
pymoul/trunk/src/moul/qt/i18n/pymoul_fr.qm
pymoul/trunk/src/moul/qt/i18n/pymoul_fr.ts
pymoul/trunk/src/moul/qt/i18n/pymoul_it.qm
pymoul/trunk/src/moul/qt/i18n/pymoul_it.ts
Property Changed:
----------------
pymoul/trunk/src/moul/qt/i18n/pymoul_de.ts
Modified: pymoul/trunk/Makefile.in
===================================================================
--- pymoul/trunk/Makefile.in 2007-01-28 15:49:22 UTC (rev 91)
+++ pymoul/trunk/Makefile.in 2007-01-28 16:43:16 UTC (rev 92)
@@ -1,5 +1,11 @@
PYTHON?=python
EPYDOC=$(PYTHON) -c "import epydoc.cli; epydoc.cli.cli()"
+NOTSVN=-a -not -wholename '*.svn*'
+FINDPYTXT=find src/moul \( -name '*.py' -o -name '*.txt' \) $(NOTSVN)
+FINDPY=find src/moul -name '*.py' $(NOTSVN)
+FINDQT=find src/moul/qt \( -name '*.py' -o -name '*.ui' \) $(NOTSVN)
+FINDTEXT=find src/moul \( -name '*.py' -o -name '*.txt' -o -name '*.qrc' -o -name '*.ui' -o -name '*.ts' \) $(NOTSVN)
+LANGS=de fr it es
TESTFLAGS=-v
TESTOPTS=
SETUPFLAGS=
@@ -60,8 +66,15 @@
$(PYTHON) setup.py clean -a
propset:
- find src/moul \( -name '*.py' -o -name '*.txt' \) -a -not -wholename '*.svn*' | xargs svn propset svn:keywords "Id Revision"
- find src/moul \( -name '*.py' -o -name '*.txt' -o -name '*.qrc' -o -name '*.ui' \) -a -not -wholename '*.svn*' | xargs svn propset svn:eol-style "native"
- find . -maxdepth 1 \( -name '*.py' -o -name '*.txt' \) | xargs svn propset svn:keywords "Id Revisioni"
- find . -maxdepth 1 \( -name '*.py' -o -name '*.txt' \) | xargs svn propset svn:eol-style "native"
+ $(FINDPYTXT) | xargs svn propset svn:keywords "Id Revision"
+ $(FINDTEXT) | xargs svn propset svn:eol-style "native"
+fixlineendings:
+ $(FINDPY) | xargs recode -f ibmpc..latin1
+
+updatelangs:
+ for L in $(LANGS); do \
+ pylupdate4 `$(FINDQT)` -ts src/moul/qt/i18n/pymoul_$${L}.ts;\
+ lrelease src/moul/qt/i18n/pymoul_$${L}.ts; \
+ done
+
Modified: pymoul/trunk/src/moul/osdependent/singleapp.py
===================================================================
--- pymoul/trunk/src/moul/osdependent/singleapp.py 2007-01-28 15:49:22 UTC (rev 91)
+++ pymoul/trunk/src/moul/osdependent/singleapp.py 2007-01-28 16:43:16 UTC (rev 92)
@@ -33,8 +33,8 @@
True
>>> os.path.isfile(lckfile)
True
->>> singleapp.checkLocked() is None
-True
+>>> singleapp.checkLocked()
+2
>>> singleapp.release()
>>> os.path.isfile(lckfile)
False
@@ -151,10 +151,10 @@
self._locked = False
def checkLocked(self):
- """Check if another process has a lock
+ """Check a process has a lock
"""
if self._locked:
- return True
+ return 2
try:
lock(self._fd, LOCK)
except (IOError, OSError):
Added: pymoul/trunk/src/moul/qt/i18n/pymoul_de.qm
===================================================================
(Binary files differ)
Property changes on: pymoul/trunk/src/moul/qt/i18n/pymoul_de.qm
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Modified: pymoul/trunk/src/moul/qt/i18n/pymoul_de.ts
===================================================================
--- pymoul/trunk/src/moul/qt/i18n/pymoul_de.ts 2007-01-28 15:49:22 UTC (rev 91)
+++ pymoul/trunk/src/moul/qt/i18n/pymoul_de.ts 2007-01-28 16:43:16 UTC (rev 92)
@@ -2,34 +2,6 @@
<context>
<name>MainWindow</name>
<message>
- <source>MOUL is running</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <source>MOUL</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <source>MOUL is not running</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <source>Not Implemented</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <source>Sorry, this feature is not implemented yet!</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <source>Error opening graphics.ini</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <source>Error opening audio.ini</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
<source>Tool for Myst Online</source>
<translation type="unfinished"></translation>
</message>
@@ -244,5 +216,33 @@
<source>About</source>
<translation type="unfinished"></translation>
</message>
+ <message>
+ <source>MOUL is running</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>MOUL</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>MOUL is not running</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Not Implemented</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Sorry, this feature is not implemented yet!</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Error opening graphics.ini</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Error opening audio.ini</source>
+ <translation type="unfinished"></translation>
+ </message>
</context>
</TS>
Property changes on: pymoul/trunk/src/moul/qt/i18n/pymoul_de.ts
___________________________________________________________________
Name: svn:eol-style
+ native
Added: pymoul/trunk/src/moul/qt/i18n/pymoul_es.qm
===================================================================
(Binary files differ)
Property changes on: pymoul/trunk/src/moul/qt/i18n/pymoul_es.qm
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: pymoul/trunk/src/moul/qt/i18n/pymoul_es.ts
===================================================================
--- pymoul/trunk/src/moul/qt/i18n/pymoul_es.ts (rev 0)
+++ pymoul/trunk/src/moul/qt/i18n/pymoul_es.ts 2007-01-28 16:43:16 UTC (rev 92)
@@ -0,0 +1,248 @@
+<!DOCTYPE TS><TS>
+<context>
+ <name>MainWindow</name>
+ <message>
+ <source>Tool for Myst Online</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Configure</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Windowed</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Vertical Sync</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Display Shadows</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Screen Resolution</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>800x600 (4:3)</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Quality</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Texture Quality</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Low</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>High</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Anti-Aliasing</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Graphics Quality</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Med.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Ultra</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Shadow Quality</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Anisotropic-Filtering</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Graphics</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Level</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>NPC Voices</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Sound FX</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Ambience Sound</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Music</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Mute all</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Hardware</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Sound Priority</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Audio Modes</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Generic Software</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Enable EAX</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Voice chat</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Microphon Level</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Enable Voice Chat</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Audio</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Time zones</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Cavern time:</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Cyan time:</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>UTC -0</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>(Mountain Standard Time)</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>(Pacific Standard Time)</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>D'ni time</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Time</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Ping servers</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Ping</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source><html><head><meta name="qrichtext" content="1" /><style type="text/css">
+p, li { white-space: pre-wrap; }
+</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal; text-decoration:none;">
+<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p></body></html></source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Servers</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Browse in game documents</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Age</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Element</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Language</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Set</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Documents</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>pyMoul tools</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>About</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>MOUL is running</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>MOUL</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>MOUL is not running</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Not Implemented</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Sorry, this feature is not implemented yet!</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Error opening graphics.ini</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Error opening audio.ini</source>
+ <translation type="unfinished"></translation>
+ </message>
+</context>
+</TS>
Property changes on: pymoul/trunk/src/moul/qt/i18n/pymoul_es.ts
___________________________________________________________________
Name: svn:eol-style
+ native
Added: pymoul/trunk/src/moul/qt/i18n/pymoul_fr.qm
===================================================================
(Binary files differ)
Property changes on: pymoul/trunk/src/moul/qt/i18n/pymoul_fr.qm
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: pymoul/trunk/src/moul/qt/i18n/pymoul_fr.ts
===================================================================
--- pymoul/trunk/src/moul/qt/i18n/pymoul_fr.ts (rev 0)
+++ pymoul/trunk/src/moul/qt/i18n/pymoul_fr.ts 2007-01-28 16:43:16 UTC (rev 92)
@@ -0,0 +1,248 @@
+<!DOCTYPE TS><TS>
+<context>
+ <name>MainWindow</name>
+ <message>
+ <source>Tool for Myst Online</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Configure</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Windowed</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Vertical Sync</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Display Shadows</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Screen Resolution</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>800x600 (4:3)</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Quality</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Texture Quality</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Low</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>High</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Anti-Aliasing</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Graphics Quality</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Med.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Ultra</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Shadow Quality</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Anisotropic-Filtering</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Graphics</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Level</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>NPC Voices</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Sound FX</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Ambience Sound</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Music</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Mute all</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Hardware</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Sound Priority</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Audio Modes</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Generic Software</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Enable EAX</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Voice chat</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Microphon Level</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Enable Voice Chat</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Audio</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Time zones</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Cavern time:</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Cyan time:</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>UTC -0</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>(Mountain Standard Time)</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>(Pacific Standard Time)</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>D'ni time</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Time</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Ping servers</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Ping</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source><html><head><meta name="qrichtext" content="1" /><style type="text/css">
+p, li { white-space: pre-wrap; }
+</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal; text-decoration:none;">
+<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p></body></html></source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Servers</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Browse in game documents</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Age</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Element</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Language</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Set</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Documents</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>pyMoul tools</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>About</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>MOUL is running</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>MOUL</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>MOUL is not running</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Not Implemented</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Sorry, this feature is not implemented yet!</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Error opening graphics.ini</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Error opening audio.ini</source>
+ <translation type="unfinished"></translation>
+ </message>
+</context>
+</TS>
Property changes on: pymoul/trunk/src/moul/qt/i18n/pymoul_fr.ts
___________________________________________________________________
Name: svn:eol-style
+ native
Added: pymoul/trunk/src/moul/qt/i18n/pymoul_it.qm
===================================================================
(Binary files differ)
Property changes on: pymoul/trunk/src/moul/qt/i18n/pymoul_it.qm
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: pymoul/trunk/src/moul/qt/i18n/pymoul_it.ts
===================================================================
--- pymoul/trunk/src/moul/qt/i18n/pymoul_it.ts (rev 0)
+++ pymoul/trunk/src/moul/qt/i18n/pymoul_it.ts 2007-01-28 16:43:16 UTC (rev 92)
@@ -0,0 +1,248 @@
+<!DOCTYPE TS><TS>
+<context>
+ <name>MainWindow</name>
+ <message>
+ <source>Tool for Myst Online</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Configure</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Windowed</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Vertical Sync</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Display Shadows</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Screen Resolution</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>800x600 (4:3)</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Quality</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Texture Quality</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Low</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>High</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Anti-Aliasing</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Graphics Quality</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Med.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Ultra</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Shadow Quality</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Anisotropic-Filtering</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Graphics</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Level</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>NPC Voices</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Sound FX</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Ambience Sound</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Music</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Mute all</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Hardware</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Sound Priority</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Audio Modes</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Generic Software</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Enable EAX</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Voice chat</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Microphon Level</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Enable Voice Chat</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Audio</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Time zones</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Cavern time:</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Cyan time:</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>UTC -0</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>(Mountain Standard Time)</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>(Pacific Standard Time)</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>D'ni time</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Time</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Ping servers</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Ping</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source><html><head><meta name="qrichtext" content="1" /><style type="text/css">
+p, li { white-space: pre-wrap; }
+</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal; text-decoration:none;">
+<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p></body></html></source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Servers</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Browse in game documents</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Age</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Element</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Language</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Set</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Documents</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>pyMoul tools</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>About</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>MOUL is running</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>MOUL</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>MOUL is not running</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Not Implemented</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Sorry, this feature is not implemented yet!</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Error opening graphics.ini</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Error opening audio.ini</source>
+ <translation type="unfinished"></translation>
+ </message>
+</context>
+</TS>
Property changes on: pymoul/trunk/src/moul/qt/i18n/pymoul_it.ts
___________________________________________________________________
Name: svn:eol-style
+ native
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <ti...@us...> - 2007-01-28 15:49:23
|
Revision: 91
http://pymoul.svn.sourceforge.net/pymoul/?rev=91&view=rev
Author: tiran
Date: 2007-01-28 07:49:22 -0800 (Sun, 28 Jan 2007)
Log Message:
-----------
Added pymoul translation file
Changed doc strings - pylupdate4's parser doesn't understand some constructs with triple quotes
Modified Paths:
--------------
pymoul/trunk/src/moul/qt/localization.py
pymoul/trunk/src/moul/qt/mainwindow.py
pymoul/trunk/src/moul/qt/moulqt.py
pymoul/trunk/src/moul/qt/ui/__init__.py
Added Paths:
-----------
pymoul/trunk/src/moul/qt/i18n/pymoul_de.ts
Added: pymoul/trunk/src/moul/qt/i18n/pymoul_de.ts
===================================================================
--- pymoul/trunk/src/moul/qt/i18n/pymoul_de.ts (rev 0)
+++ pymoul/trunk/src/moul/qt/i18n/pymoul_de.ts 2007-01-28 15:49:22 UTC (rev 91)
@@ -0,0 +1,248 @@
+<!DOCTYPE TS><TS>
+<context>
+ <name>MainWindow</name>
+ <message>
+ <source>MOUL is running</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>MOUL</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>MOUL is not running</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Not Implemented</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Sorry, this feature is not implemented yet!</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Error opening graphics.ini</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Error opening audio.ini</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Tool for Myst Online</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Configure</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Windowed</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Vertical Sync</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Display Shadows</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Screen Resolution</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>800x600 (4:3)</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Quality</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Texture Quality</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Low</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>High</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Anti-Aliasing</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Graphics Quality</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Med.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Ultra</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Shadow Quality</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Anisotropic-Filtering</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Graphics</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Level</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>NPC Voices</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Sound FX</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Ambience Sound</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Music</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Mute all</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Hardware</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Sound Priority</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Audio Modes</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Generic Software</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Enable EAX</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Voice chat</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Microphon Level</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Enable Voice Chat</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Audio</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Time zones</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Cavern time:</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Cyan time:</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>UTC -0</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>(Mountain Standard Time)</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>(Pacific Standard Time)</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>D'ni time</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Time</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Ping servers</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Ping</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source><html><head><meta name="qrichtext" content="1" /><style type="text/css">
+p, li { white-space: pre-wrap; }
+</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal; text-decoration:none;">
+<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p></body></html></source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Servers</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Browse in game documents</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Age</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Element</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Language</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Set</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Documents</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>pyMoul tools</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>About</source>
+ <translation type="unfinished"></translation>
+ </message>
+</context>
+</TS>
Modified: pymoul/trunk/src/moul/qt/localization.py
===================================================================
--- pymoul/trunk/src/moul/qt/localization.py 2007-01-28 15:23:44 UTC (rev 90)
+++ pymoul/trunk/src/moul/qt/localization.py 2007-01-28 15:49:22 UTC (rev 91)
@@ -15,6 +15,7 @@
# with this program; if not, write to the Free Software Foundation, Inc., 59
# Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
+
"""Moul localization / documents
"""
__author__ = "Christian Heimes"
@@ -43,8 +44,9 @@
return QtCore.QStringList(dummy+lst)
class LocalizationMixin(object):
- """Mixin for documents tab
"""
+ Mixin for documentation tab
+ """
def _documents_init(self):
locDir = lookupDir('loc')
if not os.path.isdir(locDir):
Modified: pymoul/trunk/src/moul/qt/mainwindow.py
===================================================================
--- pymoul/trunk/src/moul/qt/mainwindow.py 2007-01-28 15:23:44 UTC (rev 90)
+++ pymoul/trunk/src/moul/qt/mainwindow.py 2007-01-28 15:49:22 UTC (rev 91)
@@ -15,6 +15,7 @@
# with this program; if not, write to the Free Software Foundation, Inc., 59
# Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
+
"""Moul QT GUI main windows
"""
from __future__ import with_statement
@@ -47,8 +48,9 @@
LOG = getLogger('moul.qt')
def criticalMessageBox(self, title, text):
- """Critical warning!
"""
+ Critical warning!
+ """
mb = QtGui.QMessageBox()
mb.setWindowIcon(QtGui.QIcon(":/resources/uru_icon_32x32.png"))
mb.setIcon(QtGui.QMessageBox.Critical)
@@ -110,14 +112,16 @@
QtGui.QSystemTrayIcon.Information, 10000)
def _notimplemented(self):
- """TODO: remove me
"""
+ TODO: remove me
+ """
QtGui.QMessageBox.information(self,
self.trUtf8("Not Implemented"),
self.trUtf8("""Sorry, this feature is not implemented yet!"""))
def closeEvent(self, event):
- """Close event handler
+ """
+ Close event handler
@param event close event (QCloseEvent)
"""
@@ -129,7 +133,8 @@
event.accept()
def keyPressEvent(self, event):
- """Key event handler
+ """
+ Key event handler
@param event key event (QKeyEvent)
@@ -141,8 +146,9 @@
event.ignore()
def setDirty(self, boolean):
- """Sets the save state
"""
+ Sets the save state
+ """
self._dirty = bool(boolean)
#self.main_buttonbox_reset.setEnabled(boolean)
#self.main_buttonbox_save.setEnabled(boolean)
@@ -164,8 +170,9 @@
# graphics settings
def _graphics_init(self):
- """init graphics tab
"""
+ init graphics tab
+ """
self.connect(self, SIGNAL("graphicsini_loaded()"), self.on_graphicsini_loaded)
self.connect(self, SIGNAL("graphicsini_reset()"), self.on_graphicsini_reset)
self.connect(self, SIGNAL("graphicsini_save()"), self.on_graphicsini_save)
@@ -175,8 +182,9 @@
@signalLogDecorator(LOG)
def on_graphicsini_loaded(self):
- """SIGNAL graphicsini_loaded()
"""
+ SIGNAL graphicsini_loaded()
+ """
inipath = lookupDir('ini')
self._graphics_ini = gini = GraphicsIni()
try:
@@ -191,22 +199,25 @@
@signalLogDecorator(LOG)
def on_graphicsini_reset(self):
- """SIGNAL graphicsini_reset()
"""
+ SIGNAL graphicsini_reset()
+ """
self._graphics_ini.reset()
self._graphicsini_setstate()
@signalLogDecorator(LOG)
def on_graphicsini_save(self):
- """SIGNAL graphicsini_save()
"""
+ SIGNAL graphicsini_save()
+ """
#self._notimplemented()
self._graphics_ini.write()
self.setDirty(False)
def _graphicsini_setstate(self):
- """Set sliders according to graphics ini settings
"""
+ Set sliders according to graphics ini settings
+ """
gini = self._graphics_ini
length = len(videoModes) - 1
self.sl_gra_screenres.setMaximum(length)
@@ -224,8 +235,9 @@
@signalLogDecorator(LOG)
@pyqtSignature("int")
def on_sl_gra_screenres_valueChanged(self, idx):
- """SIGNAL: valueChanged (int)
"""
+ SIGNAL: valueChanged (int)
+ """
# XXX: fixme
txt = videoModes.getVidModeHuman(idx)
self.lb_screenres.setText(QtCore.QString(txt))
@@ -234,73 +246,83 @@
@signalLogDecorator(LOG)
@pyqtSignature("int")
def on_sl_gra_screenres_sliderMoved(self, idx):
- """SIGNAL: sliderMoved(int)
"""
+ SIGNAL: sliderMoved(int)
+ """
txt = videoModes.getVidModeHuman(idx)
self.lb_screenres.setText(QtCore.QString(txt))
@signalLogDecorator(LOG)
@pyqtSignature("int")
def on_sl_gra_quality_valueChanged(self, idx):
- """SIGNAL: valueChanged (int)
"""
+ SIGNAL: valueChanged (int)
+ """
self._graphics_ini.quality = idx
@signalLogDecorator(LOG)
@pyqtSignature("int")
def on_sl_gra_texture_valueChanged(self, idx):
- """SIGNAL: valueChanged (int)
"""
+ SIGNAL: valueChanged (int)
+ """
self._graphics_ini.texture = idx
@signalLogDecorator(LOG)
@pyqtSignature("int")
def on_sl_gra_antialias_valueChanged(self, idx):
- """SIGNAL: valueChanged (int)
"""
+ SIGNAL: valueChanged (int)
+ """
self._graphics_ini.antialias = idx
@signalLogDecorator(LOG)
@pyqtSignature("int")
def on_sl_gra_anisotropic_valueChanged(self, idx):
- """SIGNAL: valueChanged (int)
"""
+ SIGNAL: valueChanged (int)
+ """
self._graphics_ini.anisotropic = idx
@signalLogDecorator(LOG)
@pyqtSignature("int")
def on_sl_gra_shadow_valueChanged(self, idx):
- """SIGNAL: valueChanged (int)
"""
+ SIGNAL: valueChanged (int)
+ """
self._graphics_ini.shadow = idx
@signalLogDecorator(LOG)
@pyqtSignature("int")
def on_cb_gra_windowed_stateChanged(self, state):
- """SIGNAL: stateChanged(int)
"""
+ SIGNAL: stateChanged(int)
+ """
self._graphics_ini.windowed = state
@signalLogDecorator(LOG)
@pyqtSignature("int")
def on_cb_gra_vsync_stateChanged (self, state):
- """SIGNAL: stateChanged(int)
"""
+ SIGNAL: stateChanged(int)
+ """
self._graphics_ini.vsync = state
@signalLogDecorator(LOG)
@pyqtSignature("int")
def on_cb_gra_shadow_stateChanged (self, state):
- """SIGNAL: stateChanged(int)
"""
+ SIGNAL: stateChanged(int)
+ """
self._graphics_ini.shadow_enabled = state
# ************************************************************************
# audio settings
def _audio_init(self):
- """init graphics tab
"""
+ init graphics tab
+ """
self.connect(self, SIGNAL("audioini_loaded()"), self.on_audioini_loaded)
self.connect(self, SIGNAL("audiini_reset()"), self.on_audioini_reset)
self.connect(self, SIGNAL("audiini_save()"), self.on_audioini_save)
@@ -310,8 +332,9 @@
@signalLogDecorator(LOG)
def on_audioini_loaded(self):
- """SIGNAL: audioini_loaded()
"""
+ SIGNAL: audioini_loaded()
+ """
inipath = lookupDir('ini')
self._audio_ini = aini = AudioIni()
try:
@@ -326,22 +349,25 @@
@signalLogDecorator(LOG)
def on_audioini_reset(self):
- """SIGNAL audioini_reset()
"""
+ SIGNAL audioini_reset()
+ """
self._audio_ini.reset()
self._audioini_setstate()
@signalLogDecorator(LOG)
def on_audioini_save(self):
- """SIGNAL audioini_save()
"""
+ SIGNAL audioini_save()
+ """
#self._notimplemented()
self._audio_ini.write()
self.setDirty(False) # urks
def _audioini_setstate(self):
- """Set sliders according to audio ini settings
"""
+ Set sliders according to audio ini settings
+ """
aini = self._audio_ini
self.sl_aud_device.setMaximum(aini.numberOfDevices()-1)
@@ -358,8 +384,6 @@
@signalLogDecorator(LOG)
@pyqtSignature("int")
def on_sl_aud_device_valueChanged(self, idx):
- """SIGNAL: valueChanged (int)
- """
self._audio_ini.device = idx
txt = self._audio_ini.getDeviceName(idx)
self.lb_aud_device.setText(QtCore.QString(txt[1:-1]))
@@ -367,72 +391,55 @@
@signalLogDecorator(LOG)
@pyqtSignature("int")
def on_sl_aud_device_sliderMoved(self, idx):
- """SIGNAL: sliderMoved(int)
- """
txt = self._audio_ini.getDeviceName(idx)
self.lb_aud_device.setText(QtCore.QString(txt[1:-1]))
@signalLogDecorator(LOG)
@pyqtSignature("int")
def on_sl_aud_npc_valueChanged(self, idx):
- """SIGNAL: valueChanged (int)
- """
self._audio_ini.npc = idx
@signalLogDecorator(LOG)
@pyqtSignature("int")
def on_sl_aud_music_valueChanged(self, idx):
- """SIGNAL: valueChanged (int)
- """
self._audio_ini.music = idx
@signalLogDecorator(LOG)
@pyqtSignature("int")
def on_sl_aud_fx_valueChanged(self, idx):
- """SIGNAL: valueChanged (int)
- """
self._audio_ini.fx = idx
@signalLogDecorator(LOG)
@pyqtSignature("int")
def on_sl_aud_ambience_valueChanged(self, idx):
- """SIGNAL: valueChanged (int)
- """
self._audio_ini.ambience = idx
@signalLogDecorator(LOG)
@pyqtSignature("int")
def on_sl_aud_priority_valueChanged(self, idx):
- """SIGNAL: valueChanged (int)
- """
self._audio_ini.priority = idx
@signalLogDecorator(LOG)
@pyqtSignature("int")
def on_cb_aud_eax_stateChanged (self, state):
- """SIGNAL: stateChanged(int)
- """
self._audio_ini.eax = state
@signalLogDecorator(LOG)
@pyqtSignature("int")
def on_cb_aud_mute_stateChanged (self, state):
- """SIGNAL: stateChanged(int)
- """
self._audio_ini.mute = state
@signalLogDecorator(LOG)
@pyqtSignature("int")
def on_cb_aud_voicechat_stateChanged (self, state):
- """SIGNAL: stateChanged(int)
- """
self._audio_ini.voicechat = state
# ************************************************************************
# time zones
def _timezone_init(self):
- """Init time zone tab"""
+ """
+ Init time zone tab"""
# create info object and update display the first time
self._caverntime = CavernTime()
self._timezone_update()
@@ -445,7 +452,9 @@
timer.start()
def _timezone_update(self):
- """Update datetime widgets"""
+ """
+ Update datetime widgets
+ """
ct = self._caverntime.info()
self.dt_cavern.setDateTime(ct['cavern']['datetime'])
@@ -461,8 +470,9 @@
@pyqtSignature("")
def on_timezone_timer_timeout(self):
- """SIGNAL: QTimer timeout
"""
+ SIGNAL: QTimer timeout
+ """
ct = self._caverntime()
self.dt_cavern.setDateTime(ct['cavern'])
self.dt_pacific.setDateTime(ct['pacific'])
@@ -470,8 +480,9 @@
# ************************************************************************
# ping
def _ping_init(self):
- """init ping tab
"""
+ init ping tab
+ """
self._ping_thread = thread = PingServerThread()
self.connect(thread, SIGNAL("started"),
@@ -597,3 +608,4 @@
self.mutex.unlock()
if not self._running:
return
+
Modified: pymoul/trunk/src/moul/qt/moulqt.py
===================================================================
--- pymoul/trunk/src/moul/qt/moulqt.py 2007-01-28 15:23:44 UTC (rev 90)
+++ pymoul/trunk/src/moul/qt/moulqt.py 2007-01-28 15:49:22 UTC (rev 91)
@@ -16,6 +16,7 @@
# with this program; if not, write to the Free Software Foundation, Inc., 59
# Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
+
"""Moul QT GUI main module
"""
__author__ = "Christian Heimes"
Modified: pymoul/trunk/src/moul/qt/ui/__init__.py
===================================================================
--- pymoul/trunk/src/moul/qt/ui/__init__.py 2007-01-28 15:23:44 UTC (rev 90)
+++ pymoul/trunk/src/moul/qt/ui/__init__.py 2007-01-28 15:49:22 UTC (rev 91)
@@ -15,6 +15,7 @@
# with this program; if not, write to the Free Software Foundation, Inc., 59
# Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
+
"""
"""
__author__ = "Christian Heimes"
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <ti...@us...> - 2007-01-28 15:23:45
|
Revision: 90
http://pymoul.svn.sourceforge.net/pymoul/?rev=90&view=rev
Author: tiran
Date: 2007-01-28 07:23:44 -0800 (Sun, 28 Jan 2007)
Log Message:
-----------
Changed import behavior and fixed smaller issues in singleapp
Modified Paths:
--------------
pymoul/trunk/INSTALL.txt
pymoul/trunk/setup_win32.py
pymoul/trunk/src/moul/osdependent/__init__.py
pymoul/trunk/src/moul/osdependent/linux/__init__.py
pymoul/trunk/src/moul/osdependent/singleapp.py
pymoul/trunk/src/moul/qt/__init__.py
pymoul/trunk/src/moul/qt/ui/mainwindow.py
Added Paths:
-----------
pymoul/trunk/src/moul/qt/i18n/
Property Changed:
----------------
pymoul/trunk/
Property changes on: pymoul/trunk
___________________________________________________________________
Name: svn:ignore
- build
dist
*.e4?
+ build
dist
*.e4?
Makefile
Modified: pymoul/trunk/INSTALL.txt
===================================================================
--- pymoul/trunk/INSTALL.txt 2007-01-27 22:29:40 UTC (rev 89)
+++ pymoul/trunk/INSTALL.txt 2007-01-28 15:23:44 UTC (rev 90)
@@ -5,7 +5,7 @@
* Python 2.5.x http://www.python.org/
* easy_install http://peak.telecommunity.com/DevCenter/EasyInstall
* setuptools (via easy install)
- * PyTz (via $ easy_install pytz)
+ * PyTz (via $ easy_install-2.5 pytz)
* Qt4 GPL 4.2+ http://www.trolltech.com/developer/downloads/qt/
* PyQt4 4.1.1+ http://www.riverbankcomputing.co.uk/pyqt/
@@ -13,7 +13,7 @@
-------
* pywin32 http://sourceforge.net/projects/pywin32/
- * py2exe http://www.py2exe.org/
+ * py2exe http://www.py2exe.org/ (via $ easy_install-2.5 py2exe)
* MinGW32 compiler (bundled with Qt4)
Tools
@@ -21,6 +21,7 @@
* UPX http://upx.sourceforge.net/#download
* InnoSetup http://www.jrsoftware.org/
+ * epydoc 3.0+ (via $ easy_install-2.5 epydoc)
====================
Windows Installation
Modified: pymoul/trunk/setup_win32.py
===================================================================
--- pymoul/trunk/setup_win32.py 2007-01-27 22:29:40 UTC (rev 89)
+++ pymoul/trunk/setup_win32.py 2007-01-28 15:23:44 UTC (rev 90)
@@ -68,8 +68,7 @@
pexe = kw['options'].setdefault('py2exe', {})
pexe['compressed'] = 100 # compress zip file
pexe['optimize'] = 0 # 0,1,2
- pexe['includes'] = ['sip', 'PyQt4', 'encodings', 'encodings.*',
- 'moul.osdependent.win32', 'moul.osdependent.win32.*']
+ pexe['includes'] = ['sip', 'PyQt4', 'encodings', 'encodings.*']
# SSL currently not in use but imported by socket
pexe['excludes'] = ['_ssl', 'win32pipe', 'win32evtlog', 'win32file', 'win32api']
# added by logging.handlers.SMTPHandler but not yet required
Modified: pymoul/trunk/src/moul/osdependent/__init__.py
===================================================================
--- pymoul/trunk/src/moul/osdependent/__init__.py 2007-01-27 22:29:40 UTC (rev 89)
+++ pymoul/trunk/src/moul/osdependent/__init__.py 2007-01-28 15:23:44 UTC (rev 90)
@@ -35,6 +35,8 @@
import os
import sys
+from types import ModuleType
+
from moul.log import getLogger
from moul.osdependent.processinfo import getPids
from moul.osdependent.processinfo import getPidNames
@@ -65,7 +67,10 @@
def _importHelper(modname, names=None, target=None):
"""Import a list of variables from a module
-
+
+ >>> mod = _importHelper(sys)
+ >>> mod is sys or mod
+ True
>>> mod = _importHelper('moul.osdependent')
>>> mod == _thismodule or mod
True
@@ -88,7 +93,11 @@
>>> vars[0] is _marker
True
"""
- mod = __import__(modname, globals(), locals(), [''])
+ if not isinstance(modname, ModuleType):
+ mod = __import__(modname, globals(), locals(), [''])
+ else:
+ mod = modname
+
if names is None:
return mod
else:
@@ -107,11 +116,14 @@
# XXX: what about cygwin, bsd and others?
_thismodule = sys.modules[__name__]
if __WIN32__:
- _importHelper('moul.osdependent.win32', NAMES, target=_thismodule)
+ from moul.osdependent import win32 as osdep_win32
+ _importHelper(osdep_win32, NAMES, target=_thismodule)
elif __LINUX__:
- _importHelper('moul.osdependent.linux', NAMES, target=_thismodule)
+ from moul.osdependent import linux as osdep_linux
+ _importHelper(osdep_linux, NAMES, target=_thismodule)
elif __MACOSX__:
- _importHelper('moul.osdependent.darwin', NAMES, target=_thismodule)
+ from moul.osdependent import darwin as osdep_darwin
+ _importHelper(osdep_darwin, NAMES, target=_thismodule)
else:
raise RuntimeError('platform %s not supported' % sys.platform)
Modified: pymoul/trunk/src/moul/osdependent/linux/__init__.py
===================================================================
--- pymoul/trunk/src/moul/osdependent/linux/__init__.py 2007-01-27 22:29:40 UTC (rev 89)
+++ pymoul/trunk/src/moul/osdependent/linux/__init__.py 2007-01-28 15:23:44 UTC (rev 90)
@@ -28,7 +28,7 @@
LOG = getLogger('moul.linux')
LOG.critical('Linux support is not tested')
-MOUL_DIR = "Uru Live"
+MOUL_DIR = ".urulive"
INI_FILE = ('pyMoul', 'pymoul.ini')
EXEC_NAME = "UruLauncher"
HOME = os.environ['HOME']
Modified: pymoul/trunk/src/moul/osdependent/singleapp.py
===================================================================
--- pymoul/trunk/src/moul/osdependent/singleapp.py 2007-01-27 22:29:40 UTC (rev 89)
+++ pymoul/trunk/src/moul/osdependent/singleapp.py 2007-01-28 15:23:44 UTC (rev 90)
@@ -106,6 +106,7 @@
self.pid = pid
self.ext = ext
self._fd = None
+ self._locked = False
self.lckfile = self._genFilename()
# register atexit function
atexit.register(self.release)
@@ -123,10 +124,12 @@
if self._fd is not None:
self._fd.close()
self._fd = None
+ self._locked = False
raise SingleAppError("Another instance is already running")
else:
self._fd.write(str(self.pid))
self._fd.flush()
+ self._locked = True
LOG.info("Create lock file %s for PID %i" % (self.lckfile, self.pid))
return self.lckfile, self.pid
@@ -145,18 +148,18 @@
if os.path.isfile(self.lckfile):
LOG.info("Remove lock file %s" % self.lckfile)
os.unlink(self.lckfile)
-
+ self._locked = False
+
def checkLocked(self):
"""Check if another process has a lock
"""
+ if self._locked:
+ return True
try:
- fd = open(self.lckfile, 'a+')
- fd.close()
- except OSError:
+ lock(self._fd, LOCK)
+ except (IOError, OSError):
return True
else:
- if self._fd:
- return None
return False
def _genFilename(self):
Modified: pymoul/trunk/src/moul/qt/__init__.py
===================================================================
--- pymoul/trunk/src/moul/qt/__init__.py 2007-01-27 22:29:40 UTC (rev 89)
+++ pymoul/trunk/src/moul/qt/__init__.py 2007-01-28 15:23:44 UTC (rev 90)
@@ -15,8 +15,11 @@
# with this program; if not, write to the Free Software Foundation, Inc., 59
# Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
+
"""
+moul.qt package with Qt4 UI
"""
+
__author__ = "Christian Heimes"
__version__ = "$Id$"
__revision__ = "$Revision$"
Modified: pymoul/trunk/src/moul/qt/ui/mainwindow.py
===================================================================
--- pymoul/trunk/src/moul/qt/ui/mainwindow.py 2007-01-27 22:29:40 UTC (rev 89)
+++ pymoul/trunk/src/moul/qt/ui/mainwindow.py 2007-01-28 15:23:44 UTC (rev 90)
@@ -1,8 +1,8 @@
# -*- coding: utf-8 -*-
-# Form implementation generated from reading ui file 'src\moul\qt\ui\mainwindow.ui'
+# Form implementation generated from reading ui file 'src/moul/qt/ui/mainwindow.ui'
#
-# Created: Fri Jan 26 19:48:46 2007
+# Created: Sun Jan 28 15:25:00 2007
# by: PyQt4 UI code generator 4.1.1
#
# WARNING! All changes made in this file will be lost!
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <ti...@us...> - 2007-01-27 22:29:40
|
Revision: 89
http://pymoul.svn.sourceforge.net/pymoul/?rev=89&view=rev
Author: tiran
Date: 2007-01-27 14:29:40 -0800 (Sat, 27 Jan 2007)
Log Message:
-----------
Propset eol-style and keywords
Renamed Makefile to Makefile.in
Tests and better implementation for locking and singleapp
Modified Paths:
--------------
pymoul/trunk/compileui.py
pymoul/trunk/setup.py
pymoul/trunk/setup_win32.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/processinfo.py
pymoul/trunk/src/moul/osdependent/singleapp.py
pymoul/trunk/src/moul/osdependent/tests/test_singleapp.py
pymoul/trunk/src/moul/osdependent/win32/__init__.py
pymoul/trunk/src/moul/qt/moulqt.py
Added Paths:
-----------
pymoul/trunk/Makefile.in
pymoul/trunk/src/moul/osdependent/tests/test_processinfo.py
Removed Paths:
-------------
pymoul/trunk/Makefile
Property Changed:
----------------
pymoul/trunk/AUTHORS.txt
pymoul/trunk/GPL.txt
pymoul/trunk/INSTALL.txt
pymoul/trunk/README.txt
pymoul/trunk/compileui.py
pymoul/trunk/distutils_upx.py
pymoul/trunk/ez_setup.py
pymoul/trunk/setup.py
pymoul/trunk/setup_win32.py
pymoul/trunk/src/moul/config/tests/test_config.py
pymoul/trunk/src/moul/file/tests/audio.txt
pymoul/trunk/src/moul/file/tests/audiocaps.0.txt
pymoul/trunk/src/moul/file/tests/graphics.txt
pymoul/trunk/src/moul/file/tests/test_chatlog.py
pymoul/trunk/src/moul/file/tests/test_kiimage.py
pymoul/trunk/src/moul/file/tests/test_localization.py
pymoul/trunk/src/moul/file/tests/test_plasmalog.py
pymoul/trunk/src/moul/file/tests/test_wdysini.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/processinfo.py
pymoul/trunk/src/moul/osdependent/singleapp.py
pymoul/trunk/src/moul/osdependent/tests/__init__.py
pymoul/trunk/src/moul/osdependent/tests/test_osdependent.py
pymoul/trunk/src/moul/osdependent/tests/test_singleapp.py
pymoul/trunk/src/moul/osdependent/win32/__init__.py
pymoul/trunk/src/moul/osdependent/win32/registry.py
pymoul/trunk/src/moul/osdependent/win32/winpath.py
pymoul/trunk/src/moul/qt/localization.py
pymoul/trunk/src/moul/qt/ui/README.txt
pymoul/trunk/src/moul/server/__init__.py
pymoul/trunk/src/moul/server/ping.py
pymoul/trunk/src/moul/server/serverlist.py
pymoul/trunk/src/moul/server/tests/__init__.py
pymoul/trunk/src/moul/server/tests/test_ping.py
pymoul/trunk/src/moul/server/tests/test_serverlist.py
pymoul/trunk/src/moul/time/README.txt
pymoul/trunk/src/moul/time/tests/test_dni.py
pymoul/trunk/test.py
pymoul/trunk/version.txt
Property changes on: pymoul/trunk/AUTHORS.txt
___________________________________________________________________
Name: svn:keywords
+ Id Revisioni
Property changes on: pymoul/trunk/GPL.txt
___________________________________________________________________
Name: svn:keywords
+ Id Revisioni
Property changes on: pymoul/trunk/INSTALL.txt
___________________________________________________________________
Name: svn:keywords
+ Id Revisioni
Deleted: pymoul/trunk/Makefile
===================================================================
--- pymoul/trunk/Makefile 2007-01-27 21:30:28 UTC (rev 88)
+++ pymoul/trunk/Makefile 2007-01-27 22:29:40 UTC (rev 89)
@@ -1,61 +0,0 @@
-PYTHON?=python
-EPYDOC=$(PYTHON) -c "import epydoc.cli; epydoc.cli.cli()"
-TESTFLAGS=-v
-TESTOPTS=
-SETUPFLAGS=
-
-all: inplace
-
-# Build in-place
-inplace:
- PYTHONPATH="src" $(PYTHON) setup.py $(SETUPFLAGS) build_ext -i
-
-build: compileui
- PYTHONPATH="src" $(PYTHON) setup.py $(SETUPFLAGS) build
-
-py2exe:
- PYTHONPATH="src" $(PYTHON) setup.py $(SETUPFLAGS) py2exe
-
-innosetup:
- PYTHONPATH="src" INNOSETUP="yes" $(PYTHON) setup.py $(SETUPFLAGS) py2exe
-
-bdist_egg:
- PYTHONPATH="src" $(PYTHON) setup.py $(SETUPFLAGS) bdist_egg
-
-run: compileui
- PYTHONPATH="src" $(PYTHON) src/moul/qt/moulqt.py
-
-exerun: compileui py2exe
- dist/moulqt.exe
-
-compileui:
- $(PYTHON) compileui.py
-
-test_build: build compileui
- PYTHONPATH="src" $(PYTHON) test.py $(TESTFLAGS) $(TESTOPTS)
-
-test_inplace: compileui
- PYTHONPATH="src" $(PYTHON) test.py $(TESTFLAGS) $(TESTOPTS)
-
-doc_html:
- PYTHONPATH="src" $(EPYDOC) -v --html --output="doc/html" moul
-
-# What should the default be?
-test: test_inplace
-
-exe: py2exe
-
-installer: innosetup
-
-egg: bdist_egg
-
-doc: doc_html
-
-clean:
- find . \( -name '*.o' -o -name '*.c' -o -name '*.so' -o -name '*.py[cod]' -o -name '*.dll' \) -exec rm -f {} \;
- rm -rf build
-
-realclean: clean
- rm -f TAGS
- $(PYTHON) setup.py clean -a
-
Copied: pymoul/trunk/Makefile.in (from rev 88, pymoul/trunk/Makefile)
===================================================================
--- pymoul/trunk/Makefile.in (rev 0)
+++ pymoul/trunk/Makefile.in 2007-01-27 22:29:40 UTC (rev 89)
@@ -0,0 +1,67 @@
+PYTHON?=python
+EPYDOC=$(PYTHON) -c "import epydoc.cli; epydoc.cli.cli()"
+TESTFLAGS=-v
+TESTOPTS=
+SETUPFLAGS=
+
+all: inplace
+
+# Build in-place
+inplace:
+ PYTHONPATH="src" $(PYTHON) setup.py $(SETUPFLAGS) build_ext -i
+
+build: compileui
+ PYTHONPATH="src" $(PYTHON) setup.py $(SETUPFLAGS) build
+
+py2exe:
+ PYTHONPATH="src" $(PYTHON) setup.py $(SETUPFLAGS) py2exe
+
+innosetup:
+ PYTHONPATH="src" INNOSETUP="yes" $(PYTHON) setup.py $(SETUPFLAGS) py2exe
+
+bdist_egg:
+ PYTHONPATH="src" $(PYTHON) setup.py $(SETUPFLAGS) bdist_egg
+
+run: compileui
+ PYTHONPATH="src" $(PYTHON) src/moul/qt/moulqt.py
+
+exerun: compileui py2exe
+ dist/moulqt.exe
+
+compileui:
+ $(PYTHON) compileui.py
+
+test_build: build compileui
+ PYTHONPATH="src" $(PYTHON) test.py $(TESTFLAGS) $(TESTOPTS)
+
+test_inplace: compileui
+ PYTHONPATH="src" $(PYTHON) test.py $(TESTFLAGS) $(TESTOPTS)
+
+doc_html:
+ PYTHONPATH="src" $(EPYDOC) -v --html --output="doc/html" moul
+
+# What should the default be?
+test: test_inplace
+
+exe: py2exe
+
+installer: innosetup
+
+egg: bdist_egg
+
+doc: doc_html
+
+clean:
+ find . \( -name '*.o' -o -name '*.c' -o -name '*.so' -o -name '*.py[cod]' -o -name '*.dll' \) -exec rm -f {} \;
+ rm -rf build
+
+realclean: clean
+ rm -f TAGS
+ $(PYTHON) setup.py clean -a
+
+propset:
+ find src/moul \( -name '*.py' -o -name '*.txt' \) -a -not -wholename '*.svn*' | xargs svn propset svn:keywords "Id Revision"
+ find src/moul \( -name '*.py' -o -name '*.txt' -o -name '*.qrc' -o -name '*.ui' \) -a -not -wholename '*.svn*' | xargs svn propset svn:eol-style "native"
+ find . -maxdepth 1 \( -name '*.py' -o -name '*.txt' \) | xargs svn propset svn:keywords "Id Revisioni"
+ find . -maxdepth 1 \( -name '*.py' -o -name '*.txt' \) | xargs svn propset svn:eol-style "native"
+
Property changes on: pymoul/trunk/README.txt
___________________________________________________________________
Name: svn:keywords
+ Id Revisioni
Modified: pymoul/trunk/compileui.py
===================================================================
--- pymoul/trunk/compileui.py 2007-01-27 21:30:28 UTC (rev 88)
+++ pymoul/trunk/compileui.py 2007-01-27 22:29:40 UTC (rev 89)
@@ -3,7 +3,7 @@
"""
__author__ = "Christian Heimes"
__version__ = "$Id$"
-__revision__ = "$Revision$"
+__revision__ = "$Revision: 45 $"
import os
import re
Property changes on: pymoul/trunk/compileui.py
___________________________________________________________________
Name: svn:keywords
- Id Revision
+ Id Revisioni
Property changes on: pymoul/trunk/distutils_upx.py
___________________________________________________________________
Name: svn:keywords
+ Id Revisioni
Property changes on: pymoul/trunk/ez_setup.py
___________________________________________________________________
Name: svn:keywords
- Id Revision
+ Id Revisioni
Modified: pymoul/trunk/setup.py
===================================================================
--- pymoul/trunk/setup.py 2007-01-27 21:30:28 UTC (rev 88)
+++ pymoul/trunk/setup.py 2007-01-27 22:29:40 UTC (rev 89)
@@ -5,7 +5,7 @@
"""
__author__ = "Christian Heimes"
__version__ = "$Id$"
-__revision__ = "$Revision$"
+__revision__ = "$Revision: 58 $"
import sys
import os
Property changes on: pymoul/trunk/setup.py
___________________________________________________________________
Name: svn:keywords
- Id Revision
+ Id Revisioni
Modified: pymoul/trunk/setup_win32.py
===================================================================
--- pymoul/trunk/setup_win32.py 2007-01-27 21:30:28 UTC (rev 88)
+++ pymoul/trunk/setup_win32.py 2007-01-27 22:29:40 UTC (rev 89)
@@ -2,7 +2,7 @@
"""
__author__ = "Christian Heimes"
__version__ = "$Id$"
-__revision__ = "$Revision$"
+__revision__ = "$Revision: 86 $"
import os
import sys
Property changes on: pymoul/trunk/setup_win32.py
___________________________________________________________________
Name: svn:keywords
- Id Revision
+ Id Revisioni
Property changes on: pymoul/trunk/src/moul/config/tests/test_config.py
___________________________________________________________________
Name: svn:keywords
+ Id Revision
Property changes on: pymoul/trunk/src/moul/file/tests/audio.txt
___________________________________________________________________
Name: svn:keywords
+ Id Revision
Property changes on: pymoul/trunk/src/moul/file/tests/audiocaps.0.txt
___________________________________________________________________
Name: svn:keywords
+ Id Revision
Property changes on: pymoul/trunk/src/moul/file/tests/graphics.txt
___________________________________________________________________
Name: svn:keywords
+ Id Revision
Property changes on: pymoul/trunk/src/moul/file/tests/test_chatlog.py
___________________________________________________________________
Name: svn:keywords
+ Id Revision
Property changes on: pymoul/trunk/src/moul/file/tests/test_kiimage.py
___________________________________________________________________
Name: svn:keywords
+ Id Revision
Property changes on: pymoul/trunk/src/moul/file/tests/test_localization.py
___________________________________________________________________
Name: svn:keywords
+ Id Revision
Property changes on: pymoul/trunk/src/moul/file/tests/test_plasmalog.py
___________________________________________________________________
Name: svn:keywords
+ Id Revision
Property changes on: pymoul/trunk/src/moul/file/tests/test_wdysini.py
___________________________________________________________________
Name: svn:keywords
+ Id Revision
Modified: pymoul/trunk/src/moul/osdependent/__init__.py
===================================================================
--- pymoul/trunk/src/moul/osdependent/__init__.py 2007-01-27 21:30:28 UTC (rev 88)
+++ pymoul/trunk/src/moul/osdependent/__init__.py 2007-01-27 22:29:40 UTC (rev 89)
@@ -1,136 +1,136 @@
-# 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
-#
-"""OS dependent code for linux, mac and win32
-
->>> pids = getPids()
->>> len(pids) > 1
-True
-
->>> pids = getPidNames()
->>> found = False
->>> for pid, name in pids.items():
-... if name.lower().startswith('python'):
-... found = True
->>> found
-True
-"""
-__author__ = "Christian Heimes"
-__version__ = "$Id$"
-__revision__ = "$Revision$"
-
-import os
-import sys
-from moul.log import getLogger
-from moul.osdependent.processinfo import getPids
-from moul.osdependent.processinfo import getPidNames
-
-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?
-__CYGWIN__ = _plat('cygwin')
-__LINUX__ = _plat('linux2')
-__MACOSX__ = _plat('darwin')
-__BSD__ = _plat('freebsd') or _plat('netbsd') or _plat('openbsd')
-__POSIX__ = os.name.lower() == 'posix'
-__NT__ = os.name.lower() == 'nt'
-__INFO__ = (__WIN32__, __CYGWIN__, __LINUX__, __MACOSX__, __BSD__,
- __POSIX__, __NT__)
-
-# names to import: from moul.osdependent.ID import NAME (as NAME)
-NAMES = ('getMoulUserDataDir',
- ('getPyMoulDataDir', '_getPyMoulDataDir'), # as
- 'startMoul', 'isMoulRunning',
- )
-
-_marker = object()
-
-def _importHelper(modname, names=None, target=None):
- """Import a list of variables from a module
-
- >>> mod = _importHelper('moul.osdependent')
- >>> mod == _thismodule or mod
- True
- >>> vars = _importHelper('moul.osdependent', ('_marker', ))
- >>> vars[0] is _marker
- True
- >>> class Target(object):
- ... pass
- >>> target = Target()
- >>> vars = _importHelper('moul.osdependent', ('_marker', ), target=target)
- >>> target._marker is _marker
- True
- >>> vars[0] is _marker
- True
-
- >>> vars = _importHelper('moul.osdependent', (('_marker', 'another'), ),
- ... target=target)
- >>> target.another is _marker
- True
- >>> vars[0] is _marker
- True
- """
- mod = __import__(modname, globals(), locals(), [''])
- if names is None:
- return mod
- else:
- vars = []
- for name in names:
- if isinstance(name, (tuple, list)):
- name, nameas = name
- else:
- nameas = name
- var = getattr(mod, name)
- vars.append(var)
- if target is not None:
- setattr(target, nameas, var)
- return vars
-
-# XXX: what about cygwin, bsd and others?
-_thismodule = sys.modules[__name__]
-if __WIN32__:
- _importHelper('moul.osdependent.win32', NAMES, target=_thismodule)
-elif __LINUX__:
- _importHelper('moul.osdependent.linux', NAMES, target=_thismodule)
-elif __MACOSX__:
- _importHelper('moul.osdependent.darwin', NAMES, target=_thismodule)
-else:
- raise RuntimeError('platform %s not supported' % sys.platform)
-
-def getPyMoulDataDir(check=False):
- """Get pyMoul data directory
-
- The directory contains log files, ini files and other local stuff
- """
- datadir = _getPyMoulDataDir()
- if check:
- if os.path.abspath(datadir) != datadir:
- raise ValueError("Datadir is not absolute %s" % datadir)
- if not os.path.isdir(datadir):
- parent = os.path.abspath(os.path.join(datadir, os.pardir))
- if not os.path.isdir(parent):
- raise ValueError("Datadir's parent dir does not exist: %s"
- % par)
- else:
- LOG.debug("Creating pyMoul data dir %s" % datadir)
- os.mkdir(datadir, 0750)
- LOG.debug("Using pyMoul data dir %s" % datadir)
- return datadir
+# 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
+#
+"""OS dependent code for linux, mac and win32
+
+>>> pids = getPids()
+>>> len(pids) > 1
+True
+
+>>> pids = getPidNames()
+>>> found = False
+>>> for pid, name in pids.items():
+... if name.lower().startswith('python'):
+... found = True
+>>> found
+True
+"""
+__author__ = "Christian Heimes"
+__version__ = "$Id$"
+__revision__ = "$Revision$"
+
+import os
+import sys
+from moul.log import getLogger
+from moul.osdependent.processinfo import getPids
+from moul.osdependent.processinfo import getPidNames
+
+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?
+__CYGWIN__ = _plat('cygwin')
+__LINUX__ = _plat('linux2')
+__MACOSX__ = _plat('darwin')
+__BSD__ = _plat('freebsd') or _plat('netbsd') or _plat('openbsd')
+__POSIX__ = os.name.lower() == 'posix'
+__NT__ = os.name.lower() == 'nt'
+__INFO__ = (__WIN32__, __CYGWIN__, __LINUX__, __MACOSX__, __BSD__,
+ __POSIX__, __NT__)
+
+# names to import: from moul.osdependent.ID import NAME (as NAME)
+NAMES = ('getMoulUserDataDir',
+ ('getPyMoulDataDir', '_getPyMoulDataDir'), # as
+ 'startMoul', 'isMoulRunning',
+ )
+
+_marker = object()
+
+def _importHelper(modname, names=None, target=None):
+ """Import a list of variables from a module
+
+ >>> mod = _importHelper('moul.osdependent')
+ >>> mod == _thismodule or mod
+ True
+ >>> vars = _importHelper('moul.osdependent', ('_marker', ))
+ >>> vars[0] is _marker
+ True
+ >>> class Target(object):
+ ... pass
+ >>> target = Target()
+ >>> vars = _importHelper('moul.osdependent', ('_marker', ), target=target)
+ >>> target._marker is _marker
+ True
+ >>> vars[0] is _marker
+ True
+
+ >>> vars = _importHelper('moul.osdependent', (('_marker', 'another'), ),
+ ... target=target)
+ >>> target.another is _marker
+ True
+ >>> vars[0] is _marker
+ True
+ """
+ mod = __import__(modname, globals(), locals(), [''])
+ if names is None:
+ return mod
+ else:
+ vars = []
+ for name in names:
+ if isinstance(name, (tuple, list)):
+ name, nameas = name
+ else:
+ nameas = name
+ var = getattr(mod, name)
+ vars.append(var)
+ if target is not None:
+ setattr(target, nameas, var)
+ return vars
+
+# XXX: what about cygwin, bsd and others?
+_thismodule = sys.modules[__name__]
+if __WIN32__:
+ _importHelper('moul.osdependent.win32', NAMES, target=_thismodule)
+elif __LINUX__:
+ _importHelper('moul.osdependent.linux', NAMES, target=_thismodule)
+elif __MACOSX__:
+ _importHelper('moul.osdependent.darwin', NAMES, target=_thismodule)
+else:
+ raise RuntimeError('platform %s not supported' % sys.platform)
+
+def getPyMoulDataDir(check=False):
+ """Get pyMoul data directory
+
+ The directory contains log files, ini files and other local stuff
+ """
+ datadir = _getPyMoulDataDir()
+ if check:
+ if os.path.abspath(datadir) != datadir:
+ raise ValueError("Datadir is not absolute %s" % datadir)
+ if not os.path.isdir(datadir):
+ parent = os.path.abspath(os.path.join(datadir, os.pardir))
+ if not os.path.isdir(parent):
+ raise ValueError("Datadir's parent dir does not exist: %s"
+ % par)
+ else:
+ LOG.debug("Creating pyMoul data dir %s" % datadir)
+ os.mkdir(datadir, 0750)
+ LOG.debug("Using pyMoul data dir %s" % datadir)
+ return datadir
Property changes on: pymoul/trunk/src/moul/osdependent/__init__.py
___________________________________________________________________
Name: svn:keywords
+ Id Revision
Name: svn:eol-style
+ native
Modified: pymoul/trunk/src/moul/osdependent/darwin/__init__.py
===================================================================
--- pymoul/trunk/src/moul/osdependent/darwin/__init__.py 2007-01-27 21:30:28 UTC (rev 88)
+++ pymoul/trunk/src/moul/osdependent/darwin/__init__.py 2007-01-27 22:29:40 UTC (rev 89)
@@ -1,57 +1,57 @@
-# 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
-#
-"""moul.osdependent.darwin
-"""
-__author__ = "Christian Heimes"
-__version__ = "$Id$"
-__revision__ = "$Revision$"
-
-import os
-from subprocess import Popen
-from moul.log import getLogger
-
-LOG = getLogger('moul.darwin')
-LOG.critical('Darwin/Mac support is not tested')
-
-MOUL_DIR = "Uru Live"
-EXEC_NAME = "UruLauncher"
-HOME = os.environ['HOME']
-
-def getMoulUserDataDir():
- """Get path of MOUL data directory
-
- The MOUL data directory contains log files, chatlogs, KI images and many
- more things.
- """
- moul_data = os.path.join(HOME, MOUL_DIR)
-
-def getPyMoulDataDir():
- """Get path to the pyMoul ini directory
- """
- inidir= os.path.join(HOME, '.pymoul')
- return inidir
-
-def startMoul(installdir, *args, **kwargs):
- """Start MOUL - returns a Popen instance
-
- args are applied to the program while kwargs are applied to
- subprocess.Popen()
- """
- path = os.path.join(installdir, EXEC_NAME)
- args = ' '.join(args)
- return Popen("%s %s" % (path, args), cwd=installdir, **kwargs)
+# 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
+#
+"""moul.osdependent.darwin
+"""
+__author__ = "Christian Heimes"
+__version__ = "$Id$"
+__revision__ = "$Revision$"
+
+import os
+from subprocess import Popen
+from moul.log import getLogger
+
+LOG = getLogger('moul.darwin')
+LOG.critical('Darwin/Mac support is not tested')
+
+MOUL_DIR = "Uru Live"
+EXEC_NAME = "UruLauncher"
+HOME = os.environ['HOME']
+
+def getMoulUserDataDir():
+ """Get path of MOUL data directory
+
+ The MOUL data directory contains log files, chatlogs, KI images and many
+ more things.
+ """
+ moul_data = os.path.join(HOME, MOUL_DIR)
+
+def getPyMoulDataDir():
+ """Get path to the pyMoul ini directory
+ """
+ inidir= os.path.join(HOME, '.pymoul')
+ return inidir
+
+def startMoul(installdir, *args, **kwargs):
+ """Start MOUL - returns a Popen instance
+
+ args are applied to the program while kwargs are applied to
+ subprocess.Popen()
+ """
+ path = os.path.join(installdir, EXEC_NAME)
+ args = ' '.join(args)
+ return Popen("%s %s" % (path, args), cwd=installdir, **kwargs)
Property changes on: pymoul/trunk/src/moul/osdependent/darwin/__init__.py
___________________________________________________________________
Name: svn:keywords
+ Id Revision
Name: svn:eol-style
+ native
Modified: pymoul/trunk/src/moul/osdependent/linux/__init__.py
===================================================================
--- pymoul/trunk/src/moul/osdependent/linux/__init__.py 2007-01-27 21:30:28 UTC (rev 88)
+++ pymoul/trunk/src/moul/osdependent/linux/__init__.py 2007-01-27 22:29:40 UTC (rev 89)
@@ -1,115 +1,115 @@
-# 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
-#
-"""moul.osdependent.linux
-"""
-__author__ = "Christian Heimes"
-__version__ = "$Id$"
-__revision__ = "$Revision$"
-
-import os
-from subprocess import Popen
-from moul.log import getLogger
-
-LOG = getLogger('moul.linux')
-LOG.critical('Darwin/Mac support is not tested')
-
-MOUL_DIR = "Uru Live"
-INI_FILE = ('pyMoul', 'pymoul.ini')
-EXEC_NAME = "UruLauncher"
-HOME = os.environ['HOME']
-PROCESSES = ('urulauncher', 'uruexplorer')
-
-def getMoulUserDataDir():
- """Get path of MOUL data directory
-
- The MOUL data directory contains log files, chatlogs, KI images and many
- more things.
- """
- return os.path.join(HOME, MOUL_DIR)
-
-def getPyMoulDataDir():
- """Get path to the pyMoul ini directory
- """
- inidir= os.path.join(HOME, '.pymoul')
- return inidir
-
-def startMoul(installdir, *args, **kwargs):
- """Start MOUL - returns a Popen instance
-
- args are applied to the program while kwargs are applied to
- subprocess.Popen()
- """
- path = os.path.join(installdir, EXEC_NAME)
- args = ' '.join(args)
- return Popen("%s %s" % (path, args), cwd=installdir, **kwargs)
-
-def isMoulRunning():
- """Test if MOUL or the launcher is running
- """
- for pid, name in getCurrentPidNames().items():
- if name.lower() in PROCESSES:
- return name.lower()
- return False
-
-# process info
-# based on http://gelb.bcom.at/trac/misc/browser/processinfo
-def getCurrentPids():
- """Returns current process ids
- """
- pids = []
- for fname in os.listdir("/proc"):
- if os.path.isdir(os.path.join("/proc", fname)):
- try:
- pids.append(int(fname))
- except ValueError:
- continue
- return pids
-
-def getCurrentPidDetails():
- """Returns mapping pid -> detailed informations
- """
- mapping = {}
- for pid in getCurrentPids():
- try:
- try:
- # read entiry file to avoid race condition bugs
- fd = open('/proc/%i/status' % pid, 'rb')
- status = fd.read().split('\n')
- finally:
- if fd:
- fd.close()
- except IoError:
- continue
- details = {}
- for line in status:
- try:
- key, value = line.split(':\t')
- except ValueError:
- continue
- details[key.lower()] = value.strip()
- mapping[pid] = details
-
- return mapping
-
-def getCurrentPidNames():
- """Returns mapping pid -> name
- """
- mapping = {}
- for pid, details in getCurrentPidDetails().items():
- mapping[pid] = details.get('name', None)
- return mapping
+# 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
+#
+"""moul.osdependent.linux
+"""
+__author__ = "Christian Heimes"
+__version__ = "$Id$"
+__revision__ = "$Revision$"
+
+import os
+from subprocess import Popen
+from moul.log import getLogger
+
+LOG = getLogger('moul.linux')
+LOG.critical('Linux support is not tested')
+
+MOUL_DIR = "Uru Live"
+INI_FILE = ('pyMoul', 'pymoul.ini')
+EXEC_NAME = "UruLauncher"
+HOME = os.environ['HOME']
+PROCESSES = ('urulauncher', 'uruexplorer')
+
+def getMoulUserDataDir():
+ """Get path of MOUL data directory
+
+ The MOUL data directory contains log files, chatlogs, KI images and many
+ more things.
+ """
+ return os.path.join(HOME, MOUL_DIR)
+
+def getPyMoulDataDir():
+ """Get path to the pyMoul ini directory
+ """
+ inidir= os.path.join(HOME, '.pymoul')
+ return inidir
+
+def startMoul(installdir, *args, **kwargs):
+ """Start MOUL - returns a Popen instance
+
+ args are applied to the program while kwargs are applied to
+ subprocess.Popen()
+ """
+ path = os.path.join(installdir, EXEC_NAME)
+ args = ' '.join(args)
+ return Popen("%s %s" % (path, args), cwd=installdir, **kwargs)
+
+def isMoulRunning():
+ """Test if MOUL or the launcher is running
+ """
+ for pid, name in getCurrentPidNames().items():
+ if name.lower() in PROCESSES:
+ return name.lower()
+ return False
+
+# process info
+# based on http://gelb.bcom.at/trac/misc/browser/processinfo
+def getCurrentPids():
+ """Returns current process ids
+ """
+ pids = []
+ for fname in os.listdir("/proc"):
+ if os.path.isdir(os.path.join("/proc", fname)):
+ try:
+ pids.append(int(fname))
+ except ValueError:
+ continue
+ return pids
+
+def getCurrentPidDetails():
+ """Returns mapping pid -> detailed informations
+ """
+ mapping = {}
+ for pid in getCurrentPids():
+ try:
+ try:
+ # read entiry file to avoid race condition bugs
+ fd = open('/proc/%i/status' % pid, 'rb')
+ status = fd.read().split('\n')
+ finally:
+ if fd:
+ fd.close()
+ except IoError:
+ continue
+ details = {}
+ for line in status:
+ try:
+ key, value = line.split(':\t')
+ except ValueError:
+ continue
+ details[key.lower()] = value.strip()
+ mapping[pid] = details
+
+ return mapping
+
+def getCurrentPidNames():
+ """Returns mapping pid -> name
+ """
+ mapping = {}
+ for pid, details in getCurrentPidDetails().items():
+ mapping[pid] = details.get('name', None)
+ return mapping
Property changes on: pymoul/trunk/src/moul/osdependent/linux/__init__.py
___________________________________________________________________
Name: svn:keywords
+ Id Revision
Name: svn:eol-style
+ native
Modified: pymoul/trunk/src/moul/osdependent/processinfo.py
===================================================================
--- pymoul/trunk/src/moul/osdependent/processinfo.py 2007-01-27 21:30:28 UTC (rev 88)
+++ pymoul/trunk/src/moul/osdependent/processinfo.py 2007-01-27 22:29:40 UTC (rev 89)
@@ -29,13 +29,15 @@
>>> pids > 1
True
>>> isinstance(pids[0], (int, long))
+True
>>> cur in pids
True
>>> mapping = getPidNames()
>>> cur in mapping
->>> mapping[cur].lower() in cur
True
+>>> mapping[cur].lower() in sys.executable
+True
>>> getPidDetails('self')['name'] == getPidDetails(cur)['name']
True
Property changes on: pymoul/trunk/src/moul/osdependent/processinfo.py
___________________________________________________________________
Name: svn:keywords
+ Id Revision
Name: svn:eol-style
+ native
Modified: pymoul/trunk/src/moul/osdependent/singleapp.py
===================================================================
--- pymoul/trunk/src/moul/osdependent/singleapp.py 2007-01-27 21:30:28 UTC (rev 88)
+++ pymoul/trunk/src/moul/osdependent/singleapp.py 2007-01-27 22:29:40 UTC (rev 89)
@@ -19,55 +19,11 @@
Includes portalocker code with minor tweaks for Python 2.4+
Author: Jonathan Feinberg <jd...@po...>
- Version: $Id: portalocker.py,v 1.3 2001/05/29 18:47:55 Administrator Exp $
+ Version: $Id$
http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/65203
-Boiler plate
->>> import sys
->>> from shutil import rmtree
->>> from subprocess import Popen
->>> from StringIO import StringIO
->>> tmpdir = tempfile.mkdtemp()
->>> testfile = os.path.join(tmpdir, 'test.lck')
->>> if os.name == 'nt':
-... rm = "cmd /c del"
-... else:
-... rm = "rm"
+Unit tests for lock/unlock are in tests/test_singleapp
-Create a file and lock it for this process
->>> flags = LOCK_SH | LOCK_NB
->>> fd1 = open(testfile, 'w')
->>> fn1 = fd1.fileno()
->>> lock(fd1, flags)
->>> fd1.write('testdata')
->>> os.path.isfile(testfile)
-True
-
-Try to delete the file from another process
->>> stdout = tempfile.TemporaryFile(mode="w+")
->>> stderr = tempfile.TemporaryFile(mode="w+")
->>> popen = Popen("%s %s" % (rm, testfile), stdout=stdout, stderr=stderr)
->>> popen.wait()
-0
-
->>> stdout.seek(0)
->>> out = stdout.read()
->>> if os.name == 'nt':
-... out.endswith('test.lck\\n') or out
-True
-
->>> stderr.seek(0)
->>> stderr.read() != ''
-True
-
->>> os.path.isfile(testfile)
-True
-
-Clean up
->>> unlock(fd1)
->>> fd1.close()
->>> rmtree(tmpdir)
-
>>> singleapp = SimpleSingleApp('testapp')
>>> lckfile = singleapp.lckfile
>>> if os.path.isfile(lckfile):
@@ -109,13 +65,15 @@
# LOCK_NB = win32con.LOCKFILE_FAIL_IMMEDIATELY
# lowbits, highbits = 0, -65536
LOCK_SH, LOCK_NB = 0, 1
+ LOCK = "dummy"
elif os.name == 'posix':
import fcntl
- #LOCK_EX = fcntl.LOCK_EX
+ LOCK_EX = fcntl.LOCK_EX
LOCK_SH = fcntl.LOCK_SH
LOCK_NB = fcntl.LOCK_NB
+ LOCK = LOCK_EX | LOCK_NB
else:
- raise RuntimeError("PortaLocker only defined for nt and posix platforms")
+ raise OSError("PortaLocker only defined for nt and posix platforms")
if os.name == 'nt':
def lock(file, flags):
@@ -128,9 +86,9 @@
pass
elif os.name =='posix':
def lock(file, flags):
- return fcntl.flock(file.fileno(), flags)
+ return fcntl.lockf(file, flags)
def unlock(file):
- return fcntl.flock(file.fileno(), fcntl.LOCK_UN)
+ return fcntl.lockf(file, fcntl.LOCK_UN)
class SingleAppError(OSError):
pass
@@ -138,7 +96,6 @@
class SimpleSingleApp(object):
"""A simple single instance application implemementation
"""
- flags = LOCK_SH | LOCK_NB
def __init__(self, appname, path=TEMPDIR, user=USER, pid=PID, ext='.lck',
*args):
@@ -152,28 +109,24 @@
self.lckfile = self._genFilename()
# register atexit function
atexit.register(self.release)
-
+
def acquire(self):
"""Acquire lock
-
+
May raise an OSError
"""
- if os.path.isfile(self.lckfile):
- try:
- os.unlink(self.lckfile)
- except OSError, IOError:
- self._fd = None
- raise SingleAppError("Another instance is already running")
try:
- self._fd = open(self.lckfile, 'w')
- self._fd.write(str(self.pid))
- self._fd.flush()
- lock(self._fd, self.flags)
+ self._fd = open(self.lckfile, 'w+')
+ lock(self._fd, LOCK)
except (OSError, IOError):
- self._fd.close()
+ LOG.exception("Failed to acquire lock")
+ if self._fd is not None:
+ self._fd.close()
self._fd = None
raise SingleAppError("Another instance is already running")
else:
+ self._fd.write(str(self.pid))
+ self._fd.flush()
LOG.info("Create lock file %s for PID %i" % (self.lckfile, self.pid))
return self.lckfile, self.pid
@@ -181,11 +134,12 @@
"""Release lock
"""
try:
- unlock(self._fd)
+ if self._fd is not None:
+ unlock(self._fd)
except (SystemError, SyntaxError):
raise
except:
- pass
+ LOG.exception("Error while releasin the lock")
if self._fd:
self._fd.close()
if os.path.isfile(self.lckfile):
Property changes on: pymoul/trunk/src/moul/osdependent/singleapp.py
___________________________________________________________________
Name: svn:keywords
+ Id Revision
Property changes on: pymoul/trunk/src/moul/osdependent/tests/__init__.py
___________________________________________________________________
Name: svn:keywords
+ Id Revision
Property changes on: pymoul/trunk/src/moul/osdependent/tests/test_osdependent.py
___________________________________________________________________
Name: svn:keywords
+ Id Revision
Added: pymoul/trunk/src/moul/osdependent/tests/test_processinfo.py
===================================================================
--- pymoul/trunk/src/moul/osdependent/tests/test_processinfo.py (rev 0)
+++ pymoul/trunk/src/moul/osdependent/tests/test_processinfo.py 2007-01-27 22:29:40 UTC (rev 89)
@@ -0,0 +1,36 @@
+# 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
+#
+"""moul.osdependent.processinfo
+"""
+__author__ = "Christian Heimes"
+__version__ = "$Id$"
+__revision__ = "$Revision$"
+
+import unittest
+from doctest import DocTestSuite
+
+import moul.osdependent.processinfo
+
+def test_suite():
+ return unittest.TestSuite((
+ DocTestSuite('moul.osdependent.processinfo'),
+ ))
+
+if __name__ == '__main__':
+ unittest.main(defaultTest="test_suite")
+
Property changes on: pymoul/trunk/src/moul/osdependent/tests/test_processinfo.py
___________________________________________________________________
Name: svn:keywords
+ Id Revision
Name: svn:eol-style
+ native
Modified: pymoul/trunk/src/moul/osdependent/tests/test_singleapp.py
===================================================================
--- pymoul/trunk/src/moul/osdependent/tests/test_singleapp.py 2007-01-27 21:30:28 UTC (rev 88)
+++ pymoul/trunk/src/moul/osdependent/tests/test_singleapp.py 2007-01-27 22:29:40 UTC (rev 89)
@@ -29,11 +29,83 @@
from moul.osdependent.singleapp import unlock
from moul.osdependent.singleapp import LOCK_SH, LOCK_NB
+import sys
+import os
+import tempfile
+from shutil import rmtree
+from subprocess import Popen
+from StringIO import StringIO
+tmpdir = tempfile.mkdtemp()
+testfile = os.path.join(tmpdir, 'test.lck')
+
+if os.name == 'nt':
+ rmcmd = "cmd /c del %(testfile)s"
+else:
+ rmcmd = ("LC_ALL=C %(exe)s -c 'from fcntl import *; "
+ "fd = open(%(testfile)s, %(mode)s); "
+ "lockf(fd, LOCK_EX | LOCK_NB)'" % {'exe' : sys.executable,
+ 'mode' : '"a+"', 'testfile' : '"%(testfile)s"'})
+
+
+ #singleapp = SimpleSingleApp('testapp')
+ #lckfile = singleapp.lckfile
+ #if os.path.isfile(lckfile):
+#... os.unlink(fpath)
+ #path, pid = singleapp.acquire()
+ #path == lckfile
+#True
+ #os.path.isfile(lckfile)
+#True
+ #singleapp.checkLocked() is None
+#True
+ #singleapp.release()
+ #os.path.isfile(lckfile)
+#False
+
+class SingleAppTest(unittest.TestCase):
+
+ def test_locking(self):
+ FLAGS = LOCK_SH | LOCK_NB
+ fd = open(testfile, 'w+')
+ fd.write('testdata')
+ fd.flush()
+ self.failUnless(os.path.isfile(testfile))
+ lock(fd, FLAGS)
+ # Try to delete the file from another process
+ stdout = tempfile.TemporaryFile(mode="w+")
+ stderr = tempfile.TemporaryFile(mode="w+")
+ popen = Popen(rmcmd % {'testfile' : testfile}, stdout=stdout,
+ stderr=stderr, shell=True)
+
+ popen.wait()
+ stdout.seek(0)
+ out = stdout.read()
+ if os.name == 'nt':
+ self.failUnlessEqual(out, '')
+ elif os.name =='posix':
+ self.failUnlessEqual(out, '')
+ else:
+ raise OSError("unsupported os")
+
+ stderr.seek(0)
+ err = stderr.read()
+ if os.name == 'nt':
+ self.failUnless('IOError: [Errno 11] Resource temporarily unavailable' in err)
+ elif os.name =='posix':
+ self.failUnless('IOError: [Errno 11] Resource temporarily unavailable' in err)
+ else:
+ raise OSError("unsupported os")
+
+ self.failUnless(os.path.isfile(testfile))
+ unlock(fd)
+ fd.close()
+ rmtree(tmpdir)
+
def test_suite():
return unittest.TestSuite((
+ unittest.makeSuite(SingleAppTest),
DocTestSuite('moul.osdependent.singleapp'),
))
if __name__ == '__main__':
unittest.main(defaultTest="test_suite")
-
Property changes on: pymoul/trunk/src/moul/osdependent/tests/test_singleapp.py
___________________________________________________________________
Name: svn:keywords
+ Id Revision
Modified: pymoul/trunk/src/moul/osdependent/win32/__init__.py
===================================================================
--- pymoul/trunk/src/moul/osdependent/win32/__init__.py 2007-01-27 21:30:28 UTC (rev 88)
+++ pymoul/trunk/src/moul/osdependent/win32/__init__.py 2007-01-27 22:29:40 UTC (rev 89)
@@ -1,74 +1,74 @@
-# 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
-#
-"""moul.osdependent.win32
-"""
-__author__ = "Christian Heimes"
-__version__ = "$Id$"
-__revision__ = "$Revision$"
-
-import os
-from subprocess import Popen
-
-from moul.osdependent.win32.winpath import get_homedir as getMyDocuments
-from moul.osdependent.win32.winpath import get_appdata as getAppdata
-from moul.log import getLogger
-from moul.osdependent.processinfo import getPidNames
-
-LOG = getLogger('moul.win')
-
-MOUL_DIR = "Uru Live"
-EXEC_NAME = "UruLauncher.exe"
-# lower case
-PROCESSES = ("urulauncher.exe", "uruexplorer.exe")
-
-MYDOCS = getMyDocuments()
-MYAPPDATA = getAppdata()
-
-def getMoulUserDataDir():
- """Get path of MOUL data directory
-
- The MOUL data directory contains log files, chatlogs, KI images and many
- more things.
- """
- moul_data = os.path.join(MYDOCS, MOUL_DIR)
- return moul_data
-
-def getPyMoulDataDir():
- """Get path to the pyMoul ini file
- """
- inidir = os.path.join(MYAPPDATA , 'pyMoul')
- return inidir
-
-def startMoul(installdir, *args, **kwargs):
- """Start MOUL - returns a Popen instance
-
- args are applied to the program while kwargs are applied to
- subprocess.Popen()
- """
- path = os.path.join(installdir, EXEC_NAME)
- args = ' '.join(args)
- return Popen("%s %s" % (path, args), cwd=installdir, **kwargs)
-
-def isMoulRunning():
- """Test if MOUL or the launcher is running
- """
- for pid, name in getPidNames().items():
- if name.lower() in PROCESSES:
- return pid, name.lower()
- return False
-
+# 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
+#
+"""moul.osdependent.win32
+"""
+__author__ = "Christian Heimes"
+__version__ = "$Id$"
+__revision__ = "$Revision$"
+
+import os
+from subprocess import Popen
+
+from moul.osdependent.win32.winpath import get_homedir as getMyDocuments
+from moul.osdependent.win32.winpath import get_appdata as getAppdata
+from moul.log import getLogger
+from moul.osdependent.processinfo import getPidNames
+
+LOG = getLogger('moul.win')
+
+MOUL_DIR = "Uru Live"
+EXEC_NAME = "UruLauncher.exe"
+# lower case
+PROCESSES = ("urulauncher.exe", "uruexplorer.exe")
+
+MYDOCS = getMyDocuments()
+MYAPPDATA = getAppdata()
+
+def getMoulUserDataDir():
+ """Get path of MOUL data directory
+
+ The MOUL data directory contains log files, chatlogs, KI images and many
+ more things.
+ """
+ moul_data = os.path.join(MYDOCS, MOUL_DIR)
+ return moul_data
+
+def getPyMoulDataDir():
+ """Get path to the pyMoul ini file
+ """
+ inidir = os.path.join(MYAPPDATA , 'pyMoul')
+ return inidir
+
+def startMoul(installdir, *args, **kwargs):
+ """Start MOUL - returns a Popen instance
+
+ args are applied to the program while kwargs are applied to
+ subprocess.Popen()
+ """
+ path = os.path.join(installdir, EXEC_NAME)
+ args = ' '.join(args)
+ return Popen("%s %s" % (path, args), cwd=installdir, **kwargs)
+
+def isMoulRunning():
+ """Test if MOUL or the launcher is running
+ """
+ for pid, name in getPidNames().items():
+ if name.lower() in PROCESSES:
+ return pid, name.lower()
+ return False
+
Property changes on: pymoul/trunk/src/moul/osdependent/win32/__init__.py
___________________________________________________________________
Name: svn:keywords
+ Id Revision
Name: svn:eol-style
+ native
Property changes on: pymoul/trunk/src/moul/osdependent/win32/registry.py
___________________________________________________________________
Name: svn:keywords
+ Id Revision
Property changes on: pymoul/trunk/src/moul/osdependent/win32/winpath.py
___________________________________________________________________
Name: svn:keywords
+ Id Revision
Property changes on: pymoul/trunk/src/moul/qt/localization.py
___________________________________________________________________
Name: svn:keywords
+ Id Revision
Modified: pymoul/trunk/src/moul/qt/moulqt.py
===================================================================
--- pymoul/trunk/src/moul/qt/moulqt.py 2007-01-27 21:30:28 UTC (rev 88)
+++ pymoul/trunk/src/moul/qt/moulqt.py 2007-01-27 22:29:40 UTC (rev 89)
@@ -50,7 +50,7 @@
"""
LOG.info("Starting PyMoul QT UI with argv %s" % repr(args))
app = QtGui.QApplication(*args)
- singleapp = SimpleSingleApp('pymoulqt', path=getPyMoulDataDir())
+ singleapp = SimpleSingleApp('pymoulqt', path=getPyMoulDataDir(check=True))
try:
singleapp.acquire()
except OSError:
Property changes on: pymoul/trunk/src/moul/qt/ui/README.txt
___________________________________________________________________
Name: svn:keywords
+ Id Revision
Property changes on: pymoul/trunk/src/moul/server/__init__.py
___________________________________________________________________
Name: svn:keywords
+ Id Revision
Property changes on: pymoul/trunk/src/moul/server/ping.py
___________________________________________________________________
Name: svn:keywords
+ Id Revision
Property changes on: pymoul/trunk/src/moul/server/serverlist.py
___________________________________________________________________
Name: svn:keywords
+ Id Revision
Property changes on: pymoul/trunk/src/moul/server/tests/__init__.py
___________________________________________________________________
Name: svn:keywords
+ Id Revision
Property changes on: pymoul/trunk/src/moul/server/tests/test_ping.py
___________________________________________________________________
Name: svn:keywords
+ Id Revision
Property changes on: pymoul/trunk/src/moul/server/tests/test_serverlist.py
___________________________________________________________________
Name: svn:keywords
+ Id Revision
Property changes on: pymoul/trunk/src/moul/time/README.txt
___________________________________________________________________
Name: svn:keywords
+ Id Revision
Name: svn:eol-style
+ native
Property changes on: pymoul/trunk/src/moul/time/tests/test_dni.py
___________________________________________________________________
Name: svn:keywords
+ Id Revision
Property changes on: pymoul/trunk/test.py
___________________________________________________________________
Name: svn:keywords
- Id Revision
+ Id Revisioni
Property changes on: pymoul/trunk/version.txt
___________________________________________________________________
Name: svn:keywords
+ Id Revisioni
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <ti...@us...> - 2007-01-27 21:30:32
|
Revision: 88
http://pymoul.svn.sourceforge.net/pymoul/?rev=88&view=rev
Author: tiran
Date: 2007-01-27 13:30:28 -0800 (Sat, 27 Jan 2007)
Log Message:
-----------
Better process info API
Modified Paths:
--------------
pymoul/trunk/src/moul/osdependent/__init__.py
pymoul/trunk/src/moul/osdependent/win32/__init__.py
Added Paths:
-----------
pymoul/trunk/src/moul/osdependent/processinfo.py
Removed Paths:
-------------
pymoul/trunk/src/moul/osdependent/win32/enumprocesses.py
Modified: pymoul/trunk/src/moul/osdependent/__init__.py
===================================================================
--- pymoul/trunk/src/moul/osdependent/__init__.py 2007-01-26 19:03:20 UTC (rev 87)
+++ pymoul/trunk/src/moul/osdependent/__init__.py 2007-01-27 21:30:28 UTC (rev 88)
@@ -17,11 +17,11 @@
#
"""OS dependent code for linux, mac and win32
->>> pids = getCurrentPids()
+>>> pids = getPids()
>>> len(pids) > 1
True
->>> pids = getCurrentPidNames()
+>>> pids = getPidNames()
>>> found = False
>>> for pid, name in pids.items():
... if name.lower().startswith('python'):
@@ -36,6 +36,8 @@
import os
import sys
from moul.log import getLogger
+from moul.osdependent.processinfo import getPids
+from moul.osdependent.processinfo import getPidNames
LOG = getLogger('moul.osdependent')
@@ -57,7 +59,6 @@
NAMES = ('getMoulUserDataDir',
('getPyMoulDataDir', '_getPyMoulDataDir'), # as
'startMoul', 'isMoulRunning',
- 'getCurrentPids', 'getCurrentPidNames',
)
_marker = object()
Added: pymoul/trunk/src/moul/osdependent/processinfo.py
===================================================================
--- pymoul/trunk/src/moul/osdependent/processinfo.py (rev 0)
+++ pymoul/trunk/src/moul/osdependent/processinfo.py 2007-01-27 21:30:28 UTC (rev 88)
@@ -0,0 +1,235 @@
+# 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
+
+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))
+>>> cur in pids
+True
+
+>>> mapping = getPidNames()
+>>> cur in mapping
+>>> mapping[cur].lower() in cur
+True
+
+>>> getPidDetails('self')['name'] == getPidDetails(cur)['name']
+True
+>>> getPidDetails(cur)['name'] == mapping[cur]
+True
+"""
+__author__ = "Christian Heimes"
+__version__ = "$Id$"
+__revision__ = "$Revision$"
+
+import os
+import sys
+
+_plat = sys.platform.startswith
+if _plat('linux'):
+ PLAT = 'linux'
+ import os.path
+elif _plat('win') or _plat('cygwin'):
+ PLAT = 'win'
+ 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
+#elif _plat('darwin'):
+# pass
+else:
+ raise OSError("OS %s is not supported" % os.name)
+
+NULL = "\x00"
+
+class LinuxProcReader(object):
+ """Get process informations under Linux by reading /proc
+
+ Tested under Linux, may work on other POSIX os with /proc, too.
+ """
+
+ def getPids(self):
+ """Get a list of pids
+ """
+ pids = []
+ for name in os.listdir('/proc'):
+ if os.path.isdir('/proc/' + name):
+ try:
+ pids.append(int(name))
+ except ValueError:
+ pass
+ return pids
+
+ def getPidNames(self):
+ """Get a list of pid -> name
+ """
+ mapping = {}
+ for pid in self.getPids():
+ name = self._readProcStatus(pid, searchkey='name')
+ if name is not None:
+ mapping[pid] = name
+ return mapping
+
+ def getPidDetails(self, pid):
+ """Get detailed informations about a process
+ """
+ details = self._readProcStatus(pid)
+ details.update(self._readProcOther(pid))
+ details['cmdline'] = self._readProcCmdline(pid)
+ return details
+
+ def _readProcStatus(self, 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 = {}
+ try:
+ # read entiry file to avoid race conditions
+ lines = open('/proc/%s/status' % pid, 'r').readlines()
+ except IOError:
+ 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
+
+ def _readProcCmdline(self, pid):
+ """Read cmdline informations for pid and returns a list similar to sys.argv
+ """
+ try:
+ # read entiry file to avoid race conditions
+ data = open('/proc/%s/cmdline' % pid, 'r').read()
+ except IOError:
+ return None
+ return data.split(NULL)
+
+ def _readProcOther(self, 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('/proc/%s/cwd' % pid),
+ 'exe' : os.path.realpath('/proc/%s/exe' % 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
+ """
+ def getPids(self):
+ """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]
+
+ def getPidNames(self):
+ """Get a list of pid -> name
+ """
+ hModule = c_ulong()
+ count = c_ulong()
+ modname = c_buffer(51)
+ mapping = []
+ for pid in self.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))
+ name = u"".join([c for c in modname if c != NULL])
+ modname[:] = sizeof(modname) * NULL
+ KERNEL.CloseHandle(hProcess)
+ mapping[pid] = name
+
+ return mapping
+
+ def getPidDetails(self, 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))
+ name = u"".join([c for c in modname if c != NULL])
+ KERNEL.CloseHandle(hProcess)
+ return {'name' : name}
+
+
+# Initialize global methods
+if PLAT == 'linux':
+ _enumProcesses = LinuxProcReader()
+elif PLAT == 'win':
+ _enumProcesses = WinEnumProcesses()
+
+getPids = _enumProcesses.getPids
+getPidNames = _enumProcesses.getPidNames
+getPidDetails = _enumProcesses.getPidDetails
+
+if __name__ == '__main__':
+ print getPidNames()
+ print getPidDetails('self')
Modified: pymoul/trunk/src/moul/osdependent/win32/__init__.py
===================================================================
--- pymoul/trunk/src/moul/osdependent/win32/__init__.py 2007-01-26 19:03:20 UTC (rev 87)
+++ pymoul/trunk/src/moul/osdependent/win32/__init__.py 2007-01-27 21:30:28 UTC (rev 88)
@@ -26,8 +26,8 @@
from moul.osdependent.win32.winpath import get_homedir as getMyDocuments
from moul.osdependent.win32.winpath import get_appdata as getAppdata
-from moul.osdependent.win32.enumprocesses import enumProcesses
from moul.log import getLogger
+from moul.osdependent.processinfo import getPidNames
LOG = getLogger('moul.win')
@@ -67,18 +67,8 @@
def isMoulRunning():
"""Test if MOUL or the launcher is running
"""
- for pid, name in getCurrentPidNames().items():
+ for pid, name in getPidNames().items():
if name.lower() in PROCESSES:
- return name.lower()
+ return pid, name.lower()
return False
-def getCurrentPids():
- """Returns mapping pid -> name
- """
- return enumProcesses().keys()
-
-
-def getCurrentPidNames():
- """Returns mapping pid -> name
- """
- return enumProcesses()
Deleted: pymoul/trunk/src/moul/osdependent/win32/enumprocesses.py
===================================================================
--- pymoul/trunk/src/moul/osdependent/win32/enumprocesses.py 2007-01-26 19:03:20 UTC (rev 87)
+++ pymoul/trunk/src/moul/osdependent/win32/enumprocesses.py 2007-01-27 21:30:28 UTC (rev 88)
@@ -1,66 +0,0 @@
-"""
-Enumerates active processes as seen under windows Task Manager on Win NT/2k/XP using PSAPI.dll
-(new api for processes) and using ctypes.Use it as you please.
-
-Based on information from http://support.microsoft.com/default.aspx?scid=KB;EN-US;Q175030&ID=KB;EN-US;Q175030
-
-By Eric Koome
-email ek...@ya...
-license GPL
-
-http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/305279
-Title: getting process information on windows
-Last Updated: 2004/09/22
-Version no: 1.3
-
-Changed by Christian Heimes
-"""
-
-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
-NULL = '\x00'
-
-def enumProcesses():
- """Enumerate processes on Windows using psapi.dll
-
- @return: A mapping of pid(long) -> process name(unicode)
- """
- result = {}
- arr = c_ulong * 256
- lpidProcess = arr()
- cb = sizeof(lpidProcess)
- cbNeeded = c_ulong()
- hModule = c_ulong()
- count = c_ulong()
- modname = c_buffer(51)
-
- # 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
- pidProcess = [pid for pid in lpidProcess][:nReturned]
-
- for pid in pidProcess:
- # 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))
-
- name = u"".join([c for c in modname if c != NULL])
- result[pid] = name
-
- modname[:] = sizeof(modname) * NULL
- KERNEL.CloseHandle(hProcess)
-
- return result
-
-if __name__ == '__main__':
- from pprint import pprint
- pprint(EnumProcesses())
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <ti...@us...> - 2007-01-26 19:03:25
|
Revision: 87
http://pymoul.svn.sourceforge.net/pymoul/?rev=87&view=rev
Author: tiran
Date: 2007-01-26 11:03:20 -0800 (Fri, 26 Jan 2007)
Log Message:
-----------
Status message
More log cleanups
More logging
Modified Paths:
--------------
pymoul/trunk/src/moul/log.py
pymoul/trunk/src/moul/osdependent/singleapp.py
pymoul/trunk/src/moul/qt/mainwindow.py
pymoul/trunk/src/moul/qt/moulqt.py
pymoul/trunk/src/moul/qt/ui/mainwindow.py
pymoul/trunk/src/moul/qt/ui/mainwindow.ui
Modified: pymoul/trunk/src/moul/log.py
===================================================================
--- pymoul/trunk/src/moul/log.py 2007-01-26 18:30:56 UTC (rev 86)
+++ pymoul/trunk/src/moul/log.py 2007-01-26 19:03:20 UTC (rev 87)
@@ -72,8 +72,9 @@
"""
global mhdlr
global fhdlr
- mhdlr.setTarget(fhdlr)
- mhdlr.flush()
+ if mhdlr:
+ mhdlr.setTarget(fhdlr)
+ mhdlr.flush()
root.removeHandler(mhdlr)
del mhdlr
@@ -114,11 +115,15 @@
else:
_installMemoryHdlr()
_systemInfo()
+
+def createLogfile():
+ """Create log file and redirect stdout/stderr to logfile
+ """
_installFileHdlr()
_removeMemoryHdlr()
# Redirect stdout and stderr to logger when running as frozen app
- #sys.stdout = LoggingStdout(getLogger('stdout').info)
- #sys.stderr = LoggingStdout(getLogger('stderr').error)
+ sys.stdout = LoggingStdout(getLogger('stdout').info)
+ sys.stderr = LoggingStdout(getLogger('stderr').error)
__LOG_SIGNALS__ = not __FROZEN__
def signalLogDecorator(__logger__):
Modified: pymoul/trunk/src/moul/osdependent/singleapp.py
===================================================================
--- pymoul/trunk/src/moul/osdependent/singleapp.py 2007-01-26 18:30:56 UTC (rev 86)
+++ pymoul/trunk/src/moul/osdependent/singleapp.py 2007-01-26 19:03:20 UTC (rev 87)
@@ -87,11 +87,14 @@
__version__ = "$Id$"
__revision__ = "$Revision$"
+import atexit
import os
import getpass
+from logging import getLogger
import tempfile
-import atexit
+LOG = getLogger('singleapp')
+
TEMPDIR = tempfile.gettempdir()
USER = getpass.getuser()
PID = os.getpid()
@@ -170,7 +173,9 @@
self._fd.close()
self._fd = None
raise SingleAppError("Another instance is already running")
- return self.lckfile, self.pid
+ else:
+ LOG.info("Create lock file %s for PID %i" % (self.lckfile, self.pid))
+ return self.lckfile, self.pid
def release(self):
"""Release lock
@@ -184,6 +189,7 @@
if self._fd:
self._fd.close()
if os.path.isfile(self.lckfile):
+ LOG.info("Remove lock file %s" % self.lckfile)
os.unlink(self.lckfile)
def checkLocked(self):
Modified: pymoul/trunk/src/moul/qt/mainwindow.py
===================================================================
--- pymoul/trunk/src/moul/qt/mainwindow.py 2007-01-26 18:30:56 UTC (rev 86)
+++ pymoul/trunk/src/moul/qt/mainwindow.py 2007-01-26 19:03:20 UTC (rev 87)
@@ -83,15 +83,32 @@
self._documents_init()
# run checker
+ self._moulrunning = None
self._moulrunning_thread = MoulRunningThread()
self.connect(self._moulrunning_thread, SIGNAL('moulIsRunning(bool)'),
self.on_moulIsRunning)
self._moulrunning_thread.startChecker(5.0) # check now and every 5 seconds
@signalLogDecorator(LOG)
- def on_moulIsRunning(self, bool):
- pass
-
+ def on_moulIsRunning(self, boolean):
+ sb = self.statusbar
+ boolean = bool(boolean)
+ if boolean is not self._moulrunning:
+ self._moulrunning = boolean
+ self.systemtray.setToolTip
+ if boolean:
+ msg = self.trUtf8("MOUL is running")
+ sb.showMessage(msg)
+ self.systemtray.setToolTip(msg)
+ self.systemtray.showMessage(self.trUtf8('MOUL'), msg,
+ QtGui.QSystemTrayIcon.Information, 10000)
+ else:
+ msg = self.trUtf8("MOUL is not running")
+ sb.showMessage(msg)
+ self.systemtray.setToolTip(msg)
+ self.systemtray.showMessage(self.trUtf8('MOUL'), msg,
+ QtGui.QSystemTrayIcon.Information, 10000)
+
def _notimplemented(self):
"""TODO: remove me
"""
Modified: pymoul/trunk/src/moul/qt/moulqt.py
===================================================================
--- pymoul/trunk/src/moul/qt/moulqt.py 2007-01-26 18:30:56 UTC (rev 86)
+++ pymoul/trunk/src/moul/qt/moulqt.py 2007-01-26 19:03:20 UTC (rev 87)
@@ -31,8 +31,24 @@
from moul.osdependent.singleapp import SimpleSingleApp
from moul.config import getPyMoulDataDir
from moul.osdependent import isMoulRunning
+from moul.log import createLogfile
+from moul.log import getLogger
+LOG = getLogger('moul.qt')
+
def main(*args):
+ """Main application
+
+ Flow diagram:
+ * create app
+ * check if other instance of pymoulqt is running
+ o exit app if another instance is running
+ * create log file handler
+ * check if URU is running
+ o exit if URU is running
+ * Show the main window
+ """
+ LOG.info("Starting PyMoul QT UI with argv %s" % repr(args))
app = QtGui.QApplication(*args)
singleapp = SimpleSingleApp('pymoulqt', path=getPyMoulDataDir())
try:
@@ -43,16 +59,22 @@
"""An instance of pyMoul QT is already running!""")
mb.exec_()
sys.exit(1)
- if isMoulRunning():
- mb = criticalMessageBox(app,
- "URU is running",
- """URU is running! Please close Uru or Uru Launcher first.""")
- mb.exec_()
- sys.exit(2)
+
+ createLogfile()
+
+# if isMoulRunning():
+# mb = criticalMessageBox(app,
+# "URU is running",
+# """URU is running! Please close Uru or Uru Launcher first.""")
+# mb.exec_()
+# sys.exit(2)
+ LOG.info("Invoking PyMoul QT MainWindow")
mainWindow = MainWindow()
mainWindow.show()
- return app.exec_()
+ err = app.exec_()
+ LOG.info("Exiting PyMoul QT UI with status %i" % err)
+ return err
if __name__ == '__main__':
err = main(sys.argv)
Modified: pymoul/trunk/src/moul/qt/ui/mainwindow.py
===================================================================
--- pymoul/trunk/src/moul/qt/ui/mainwindow.py 2007-01-26 18:30:56 UTC (rev 86)
+++ pymoul/trunk/src/moul/qt/ui/mainwindow.py 2007-01-26 19:03:20 UTC (rev 87)
@@ -2,7 +2,7 @@
# Form implementation generated from reading ui file 'src\moul\qt\ui\mainwindow.ui'
#
-# Created: Fri Jan 26 14:28:09 2007
+# Created: Fri Jan 26 19:48:46 2007
# by: PyQt4 UI code generator 4.1.1
#
# WARNING! All changes made in this file will be lost!
@@ -14,7 +14,7 @@
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.setWindowModality(QtCore.Qt.NonModal)
- MainWindow.resize(QtCore.QSize(QtCore.QRect(0,0,460,530).size()).expandedTo(MainWindow.minimumSizeHint()))
+ MainWindow.resize(QtCore.QSize(QtCore.QRect(0,0,460,534).size()).expandedTo(MainWindow.minimumSizeHint()))
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Policy(0),QtGui.QSizePolicy.Policy(0))
sizePolicy.setHorizontalStretch(0)
Modified: pymoul/trunk/src/moul/qt/ui/mainwindow.ui
===================================================================
--- pymoul/trunk/src/moul/qt/ui/mainwindow.ui 2007-01-26 18:30:56 UTC (rev 86)
+++ pymoul/trunk/src/moul/qt/ui/mainwindow.ui 2007-01-26 19:03:20 UTC (rev 87)
@@ -10,7 +10,7 @@
<x>0</x>
<y>0</y>
<width>460</width>
- <height>530</height>
+ <height>534</height>
</rect>
</property>
<property name="sizePolicy" >
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <ti...@us...> - 2007-01-26 18:46:01
|
Revision: 86
http://pymoul.svn.sourceforge.net/pymoul/?rev=86&view=rev
Author: tiran
Date: 2007-01-26 10:30:56 -0800 (Fri, 26 Jan 2007)
Log Message:
-----------
More cleanups: removed unused processinfo module
Removed dependency on pywin32 again. Apparently windows locks the file
Modified Paths:
--------------
pymoul/trunk/setup_win32.py
pymoul/trunk/src/moul/osdependent/singleapp.py
pymoul/trunk/src/moul/osdependent/tests/test_singleapp.py
Removed Paths:
-------------
pymoul/trunk/src/moul/osdependent/processinfo.py
Modified: pymoul/trunk/setup_win32.py
===================================================================
--- pymoul/trunk/setup_win32.py 2007-01-26 17:37:52 UTC (rev 85)
+++ pymoul/trunk/setup_win32.py 2007-01-26 18:30:56 UTC (rev 86)
@@ -71,9 +71,7 @@
pexe['includes'] = ['sip', 'PyQt4', 'encodings', 'encodings.*',
'moul.osdependent.win32', 'moul.osdependent.win32.*']
# SSL currently not in use but imported by socket
- pexe['excludes'] = ['_ssl']
- # added by platform but not yet required
- #pexe['excludes'].extend(('win32pipe', 'win32api', 'win32con', 'win32evtlog'))
+ pexe['excludes'] = ['_ssl', 'win32pipe', 'win32evtlog', 'win32file', 'win32api']
# added by logging.handlers.SMTPHandler but not yet required
pexe['excludes'].append('smtplib')
# UPX
Deleted: pymoul/trunk/src/moul/osdependent/processinfo.py
===================================================================
--- pymoul/trunk/src/moul/osdependent/processinfo.py 2007-01-26 17:37:52 UTC (rev 85)
+++ pymoul/trunk/src/moul/osdependent/processinfo.py 2007-01-26 18:30:56 UTC (rev 86)
@@ -1,219 +0,0 @@
-#!/usr/bin/env python
-# -*- coding: iso-8859-1 -*-
-"""Process info
-
-Based on http://gelb.bcom.at/trac/misc/browser/processinfo
-
-Modified and optimized by Christian Heimes
-"""
-
-import sys
-import os
-
-__all__ = ['PLATFORM', 'UnsupportedOsError', 'getCurrentPids',
- 'getCurrentPidNames', 'getCurrentPidDetails']
-
-class UnsupportedOsError(NotImplementedError):
- pass
-
-PLATFORM = None
-
-_plat = sys.platform.startswith
-if _plat('win'):
- PLATFORM = 'win'
- win32process = None
- ctypes = None
- import csv
- try:
- import win32process
- except ImportError:
- try:
- import ctypes
- except ImportError:
- pass
-elif _plat('linux2') or _plat('cygwin'):
- PLATFORM = 'linux' # Linux or Cygwin
-elif _plat('darwin'):
- # XXX: unsupported
- PLATFORM = 'mac' # Mac OS X
-elif _plat('freebsd') or _plat('netbsd') or _plat('openbsd'):
- # XXX: unsupported
- PLATFORM = 'bsd' # *BSD
-else:
- PLATFORM = 'unknown'
- raise UnsupportedOsError(sys.platform)
-
-# ****************************************************************************
-# Linux / cygwin implementation
-
-def _getCurrentPids_linux():
- """
- Returns current process-id's.
-
- :return: list with process-id's.
- """
- pids = []
- for fname in os.listdir("/proc"):
- if os.path.isdir(os.path.join("/proc", fname)):
- try:
- pids.append(int(fname))
- except ValueError:
- continue
- return pids
-
-def _getCurrentPidDetails_linux():
- """Returns mapping pid -> detailed informations
- """
- mapping = {}
- for pid in getCurrentPids():
- try:
- try:
- # read entiry file to avoid race condition bugs
- fd = open('/proc/%i/status' % pid, 'rb')
- status = fd.read().split('\n')
- finally:
- if fd:
- fd.close()
- except IoError:
- continue
- details = {}
- for line in status:
- try:
- key, value = line.split(':\t')
- except ValueError:
- continue
- details[key.lower()] = value.strip()
- mapping[pid] = details
-
- return mapping
-
-def _getCurrentPidNames_linux():
- """Returns mapping pid -> name
- """
- mapping = {}
- for pid, details in getCurrentPidDetails().items():
- mapping[pid] = details.get('name', None)
- return mapping
-
-
-# ****************************************************************************
-# Windows / win32 implementaton
-
-def _getCurrentPids_win():
- """
- Returns current process-id's.
-
- :return: List with process-id's.
- """
- if win32process is not None:
- return list(win32process.EnumProcesses())
- elif ctypes is not None:
- # ctypes is installed --> try psapi.dll
- psapi = ct.windll.psapi
- arr = ct.c_long * 1024
- process_ids = arr()
- cb = ct.sizeof(process_ids)
- bytes_returned = ct.c_ulong()
- psapi.EnumProcesses(ct.byref(process_ids), cb, ct.byref(bytes_returned))
- return sorted(list(set(process_ids)))
- else:
- csvlines = []
- current_pids = []
- for line in os.popen("tasklist.exe /fo csv /nh"):
- line = line.strip()
- if line:
- csvlines.append(line)
- for line in csv.reader(csvlines):
- current_pids.append(int(line[1]))
- if not csvlines:
- raise NotImplementedError("tasklist.exe not found (>WinXP)")
- return current_pids
-
-def _getCurrentPidNames_win():
- """Returns mapping pid -> name
- """
- mapping = {}
- for pid, details in getCurrentPidDetails().items():
- mapping[pid] = details.get('name', None)
- return mapping
-
-def _getCurrentPidDetails_win():
- """
- Returns processinfos. (pid, name and size_kb)
- """
- result = {}
-
- # tasklist.exe runs on Windows XP and higher. (To parse the ouput of
- # tasklist.exe is faster than WMI.)
- csvlines = []
- for line in os.popen("tasklist.exe /fo csv /nh"):
- line = line.strip()
- if line:
- csvlines.append(line)
- for line in csv.reader(csvlines):
- pid = int(line[1])
- details = {
- "name": line[0].decode("cp850"), # to unicode
- "pid": pid,
- }
- value = "".join(
- char for char in line[4]
- if char.isdigit()
- )
- details["size_kb"] = int(value)
- retdict[pid] = details
- if not csvlines:
- try:
- from win32com.client import GetObject
- # pywin32 is installed --> use WMI
- wmi = GetObject('winmgmts:')
- processes = wmi.InstancesOf('Win32_Process')
- for process in processes:
- pid = int(process.Properties_("ProcessId").value)
- details = {
- "name": process.Properties_("Name").value,
- "pid": pid,
- "size_kb": int(process.Properties_("WorkingSetSize").value) / 1000
- }
- retdict[pid] = details
- except ImportError:
- raise NotImplementedError("No tasklist.exe and no WMI.")
- return retdict
-
-# ****************************************************************************
-# general
-
-def unsupported():
- """Platform not supported
- """
- raise UnsupportedOsError(PLATFORM)
-unsupported.__unsupported__ = True
-
-def _initialize():
- mod = sys.modules[__name__]
- for name in ('getCurrentPids','getCurrentPidDetails', 'getCurrentPidNames'):
- func = getattr(mod, "_%s_%s" % (name, PLATFORM), None)
- if func is None:
- func = unsupported
- else:
- func.__name__ = name
- setattr(mod, name, func)
-_initialize()
-
-def main():
- """Testing"""
-
- from pprint import pformat
- # Current PIDs
- current_pids = getCurrentPids()
- print "Current PIDs: %s" % pformat(current_pids)
- print
- print "Current PID Count: %s" % len(current_pids)
- print
-
- print "Current PIDs with names: %s" % pformat(getCurrentPidNames())
- print
-
-if __name__ == "__main__":
- main()
-
Modified: pymoul/trunk/src/moul/osdependent/singleapp.py
===================================================================
--- pymoul/trunk/src/moul/osdependent/singleapp.py 2007-01-26 17:37:52 UTC (rev 85)
+++ pymoul/trunk/src/moul/osdependent/singleapp.py 2007-01-26 18:30:56 UTC (rev 86)
@@ -25,11 +25,12 @@
Boiler plate
>>> import sys
>>> from shutil import rmtree
->>> from subprocess import call
+>>> from subprocess import Popen
+>>> from StringIO import StringIO
>>> tmpdir = tempfile.mkdtemp()
>>> testfile = os.path.join(tmpdir, 'test.lck')
>>> if os.name == 'nt':
-... rm = "del"
+... rm = "cmd /c del"
... else:
... rm = "rm"
@@ -39,20 +40,29 @@
>>> fn1 = fd1.fileno()
>>> lock(fd1, flags)
>>> fd1.write('testdata')
+>>> os.path.isfile(testfile)
+True
Try to delete the file from another process
->>> try:
-... retcode = call("%s %s" % (rm, testfile))
-... except:
-... typ, value, tb = sys.exc_info()
-... del tb
-... else:
-... print "Should have raised an error!"
+>>> stdout = tempfile.TemporaryFile(mode="w+")
+>>> stderr = tempfile.TemporaryFile(mode="w+")
+>>> popen = Popen("%s %s" % (rm, testfile), stdout=stdout, stderr=stderr)
+>>> popen.wait()
+0
-On Windows the error is WindowsError based on OSError
->>> issubclass(typ, OSError) or typ
+>>> stdout.seek(0)
+>>> out = stdout.read()
+>>> if os.name == 'nt':
+... out.endswith('test.lck\\n') or out
True
+>>> stderr.seek(0)
+>>> stderr.read() != ''
+True
+
+>>> os.path.isfile(testfile)
+True
+
Clean up
>>> unlock(fd1)
>>> fd1.close()
@@ -86,17 +96,19 @@
USER = getpass.getuser()
PID = os.getpid()
+# PYWIN32: Apparently windows locks a file automatically
if os.name == 'nt':
- import win32con
- import win32file
- import pywintypes
- LOCK_EX = win32con.LOCKFILE_EXCLUSIVE_LOCK
- LOCK_SH = 0 # the default
- LOCK_NB = win32con.LOCKFILE_FAIL_IMMEDIATELY
- lowbits, highbits = 0, -65536
+# import win32con
+# import win32file
+# import pywintypes
+# LOCK_EX = win32con.LOCKFILE_EXCLUSIVE_LOCK
+# LOCK_SH = 0 # the default
+# LOCK_NB = win32con.LOCKFILE_FAIL_IMMEDIATELY
+# lowbits, highbits = 0, -65536
+ LOCK_SH, LOCK_NB = 0, 1
elif os.name == 'posix':
import fcntl
- LOCK_EX = fcntl.LOCK_EX
+ #LOCK_EX = fcntl.LOCK_EX
LOCK_SH = fcntl.LOCK_SH
LOCK_NB = fcntl.LOCK_NB
else:
@@ -104,11 +116,13 @@
if os.name == 'nt':
def lock(file, flags):
- hfile = win32file._get_osfhandle(file.fileno())
- return win32file.LockFileEx(hfile, flags, lowbits, highbits, pywintypes.OVERLAPPED())
+ #hfile = win32file._get_osfhandle(file.fileno())
+ #return win32file.LockFileEx(hfile, flags, lowbits, highbits, pywintypes.OVERLAPPED())
+ pass
def unlock(file):
- hfile = win32file._get_osfhandle(file.fileno())
- return win32file.UnlockFileEx(hfile, lowbits, highbits, pywintypes.OVERLAPPED())
+ #hfile = win32file._get_osfhandle(file.fileno())
+ #return win32file.UnlockFileEx(hfile, lowbits, highbits, pywintypes.OVERLAPPED())
+ pass
elif os.name =='posix':
def lock(file, flags):
return fcntl.flock(file.fileno(), flags)
@@ -141,6 +155,12 @@
May raise an OSError
"""
+ if os.path.isfile(self.lckfile):
+ try:
+ os.unlink(self.lckfile)
+ except OSError, IOError:
+ self._fd = None
+ raise SingleAppError("Another instance is already running")
try:
self._fd = open(self.lckfile, 'w')
self._fd.write(str(self.pid))
Modified: pymoul/trunk/src/moul/osdependent/tests/test_singleapp.py
===================================================================
--- pymoul/trunk/src/moul/osdependent/tests/test_singleapp.py 2007-01-26 17:37:52 UTC (rev 85)
+++ pymoul/trunk/src/moul/osdependent/tests/test_singleapp.py 2007-01-26 18:30:56 UTC (rev 86)
@@ -27,7 +27,7 @@
from moul.osdependent.singleapp import SimpleSingleApp
from moul.osdependent.singleapp import lock
from moul.osdependent.singleapp import unlock
-from moul.osdependent.singleapp import LOCK_EX, LOCK_SH, LOCK_NB
+from moul.osdependent.singleapp import LOCK_SH, LOCK_NB
def test_suite():
return unittest.TestSuite((
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <ti...@us...> - 2007-01-26 17:37:54
|
Revision: 85
http://pymoul.svn.sourceforge.net/pymoul/?rev=85&view=rev
Author: tiran
Date: 2007-01-26 09:37:52 -0800 (Fri, 26 Jan 2007)
Log Message:
-----------
Finally a fast and working enumProcess function ... :)
Modified Paths:
--------------
pymoul/trunk/src/moul/osdependent/win32/__init__.py
pymoul/trunk/src/moul/osdependent/win32/enumprocesses.py
pymoul/trunk/src/moul/qt/mainwindow.py
pymoul/trunk/src/moul/qt/moulqt.py
Removed Paths:
-------------
pymoul/trunk/src/moul/osdependent/win32/miniwinshell.py
pymoul/trunk/src/moul/osdependent/win32/processinfo.py
pymoul/trunk/src/moul/osdependent/win32/wmi.py
Modified: pymoul/trunk/src/moul/osdependent/win32/__init__.py
===================================================================
--- pymoul/trunk/src/moul/osdependent/win32/__init__.py 2007-01-26 16:40:35 UTC (rev 84)
+++ pymoul/trunk/src/moul/osdependent/win32/__init__.py 2007-01-26 17:37:52 UTC (rev 85)
@@ -24,11 +24,9 @@
import os
from subprocess import Popen
-from moul.osdependent.win32.miniwinshell import my_documents as getMyDocuments
-from moul.osdependent.win32.miniwinshell import application_data as getAppdata
-#from moul.osdependent.win32.winpath import get_homedir as getMyDocuments
-#from moul.osdependent.win32.winpath import get_appdata as getAppdata
-from moul.osdependent.win32 import wmi
+from moul.osdependent.win32.winpath import get_homedir as getMyDocuments
+from moul.osdependent.win32.winpath import get_appdata as getAppdata
+from moul.osdependent.win32.enumprocesses import enumProcesses
from moul.log import getLogger
LOG = getLogger('moul.win')
@@ -38,7 +36,6 @@
# lower case
PROCESSES = ("urulauncher.exe", "uruexplorer.exe")
-MYCOMPUTER = None # wmi instance
MYDOCS = getMyDocuments()
MYAPPDATA = getAppdata()
@@ -78,18 +75,10 @@
def getCurrentPids():
"""Returns mapping pid -> name
"""
- global MYCOMPUTER
- if MYCOMPUTER is None:
- # XXX: extremely slow, also see getCurrentPidNames
- MYCOMPUTER = wmi.WMI()
- return [process.ProcessId for process in MYCOMPUTER.Win32_Process()]
+ return enumProcesses().keys()
+
def getCurrentPidNames():
"""Returns mapping pid -> name
"""
- global MYCOMPUTER
- if MYCOMPUTER is None:
- MYCOMPUTER = wmi.WMI()
- return dict([(process.ProcessId, process.Name)
- for process in MYCOMPUTER.Win32_Process()
- ])
+ return enumProcesses()
Modified: pymoul/trunk/src/moul/osdependent/win32/enumprocesses.py
===================================================================
--- pymoul/trunk/src/moul/osdependent/win32/enumprocesses.py 2007-01-26 16:40:35 UTC (rev 84)
+++ pymoul/trunk/src/moul/osdependent/win32/enumprocesses.py 2007-01-26 17:37:52 UTC (rev 85)
@@ -7,57 +7,60 @@
By Eric Koome
email ek...@ya...
license GPL
+
+http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/305279
+Title: getting process information on windows
+Last Updated: 2004/09/22
+Version no: 1.3
+
+Changed by Christian Heimes
"""
-#http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/305279
-#Title: getting process information on windows
-#Submitter: Eric Koome (other recipes)
-#Last Updated: 2004/09/22
-#Version no: 1.3
-#Category:
-from ctypes import *
+from ctypes import windll, c_ulong, sizeof, c_buffer, byref
-#PSAPI.DLL
-psapi = windll.psapi
-#Kernel32.DLL
-kernel = windll.kernel32
+PSAPI = windll.psapi
+KERNEL = windll.kernel32
+PROCESS_QUERY_INFORMATION = 0x0400
+PROCESS_VM_READ = 0x0010
+PROCESS_FLAGS = PROCESS_QUERY_INFORMATION | PROCESS_VM_READ
+NULL = '\x00'
-def EnumProcesses():
+def enumProcesses():
+ """Enumerate processes on Windows using psapi.dll
+
+ @return: A mapping of pid(long) -> process name(unicode)
+ """
+ result = {}
arr = c_ulong * 256
- lpidProcess= arr()
+ lpidProcess = arr()
cb = sizeof(lpidProcess)
cbNeeded = c_ulong()
hModule = c_ulong()
count = c_ulong()
- modname = c_buffer(30)
- PROCESS_QUERY_INFORMATION = 0x0400
- PROCESS_VM_READ = 0x0010
+ modname = c_buffer(51)
- #Call Enumprocesses to get hold of process id's
- psapi.EnumProcesses(byref(lpidProcess),
- cb,
- byref(cbNeeded))
+ # 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
+ pidProcess = [pid for pid in lpidProcess][:nReturned]
- #Number of processes returned
- nReturned = cbNeeded.value/sizeof(c_ulong())
-
- pidProcess = [i for i in lpidProcess][:nReturned]
-
for pid in pidProcess:
-
- #Get handle to the process based on PID
- hProcess = kernel.OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ,
- False, pid)
+ # 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))
- print "".join([ i for i in modname if i != '\x00'])
+ PSAPI.EnumProcessModules(hProcess, byref(hModule),
+ sizeof(hModule), byref(count))
+ PSAPI.GetModuleBaseNameA(hProcess, hModule.value, modname,
+ sizeof(modname))
+
+ name = u"".join([c for c in modname if c != NULL])
+ result[pid] = name
- #-- Clean up
- for i in range(modname._length_):
- modname[i]='\x00'
-
- kernel.CloseHandle(hProcess)
+ modname[:] = sizeof(modname) * NULL
+ KERNEL.CloseHandle(hProcess)
+ return result
+
if __name__ == '__main__':
- EnumProcesses()
\ No newline at end of file
+ from pprint import pprint
+ pprint(EnumProcesses())
Deleted: pymoul/trunk/src/moul/osdependent/win32/miniwinshell.py
===================================================================
--- pymoul/trunk/src/moul/osdependent/win32/miniwinshell.py 2007-01-26 16:40:35 UTC (rev 84)
+++ pymoul/trunk/src/moul/osdependent/win32/miniwinshell.py 2007-01-26 17:37:52 UTC (rev 85)
@@ -1,141 +0,0 @@
-"""winshell - convenience functions to access Windows shell functionality
-
-Certain aspects of the Windows user interface are grouped by
- Microsoft as Shell functions. These include the Desktop, shortcut
- icons, special folders (such as My Documents) and a few other things.
-
-These are mostly available via the shell module of the win32all
- extensions, but whenever I need to use them, I've forgotten the
- various constants and so on.
-
-Several of the shell items have two variants: personal and common,
- or User and All Users. These refer to systems with profiles in use:
- anything from NT upwards, and 9x with Profiles turned on. Where
- relevant, the Personal/User version refers to that owned by the
- logged-on user and visible only to that user; the Common/All Users
- version refers to that maintained by an Administrator and visible
- to all users of the system.
-
-(c) Tim Golden <win...@ti...> 25th November 2003
-Licensed under the (GPL-compatible) MIT License:
-http://www.opensource.org/licenses/mit-license.php
-
-9th Nov 2005 0.2 . License changed to MIT
- . Added functionality using SHFileOperation
-25th Nov 2003 0.1 . Initial release by Tim Golden
-
-
-THIS IS A STRIPPED DOWN VERSION OF WINSHELL
-It contains only small subset to keep the build small
-"""
-
-__VERSION__ = "0.2small"
-
-from win32com.shell import shell, shellcon
-#import pythoncom
-
-#
-# Although this can be done in one call, Win9x didn't
-# support it, so I added this workaround.
-#
-def get_path (folder_id):
- return shell.SHGetPathFromIDList (shell.SHGetSpecialFolderLocation (0, folder_id))
-
-def desktop (common=0):
- "What folder is equivalent to the current desktop?"
- return get_path ((shellcon.CSIDL_DESKTOP, shellcon.CSIDL_COMMON_DESKTOPDIRECTORY)[common])
-
-def common_desktop ():
-#
-# Only here because already used in code
-#
- return desktop (common=1)
-
-def application_data (common=0):
- "What folder holds application configuration files?"
- return get_path ((shellcon.CSIDL_APPDATA, shellcon.CSIDL_COMMON_APPDATA)[common])
-
-def favourites (common=0):
- "What folder holds the Explorer favourites shortcuts?"
- return get_path ((shellcon.CSIDL_FAVORITES, shellcon.CSIDL_COMMON_FAVORITES)[common])
-bookmarks = favourites
-
-def start_menu (common=0):
- "What folder holds the Start Menu shortcuts?"
- return get_path ((shellcon.CSIDL_STARTMENU, shellcon.CSIDL_COMMON_STARTMENU)[common])
-
-def programs (common=0):
- "What folder holds the Programs shortcuts (from the Start Menu)?"
- return get_path ((shellcon.CSIDL_PROGRAMS, shellcon.CSIDL_COMMON_PROGRAMS)[common])
-
-def startup (common=0):
- "What folder holds the Startup shortcuts (from the Start Menu)?"
- return get_path ((shellcon.CSIDL_STARTUP, shellcon.CSIDL_COMMON_STARTUP)[common])
-
-def personal_folder ():
- "What folder holds the My Documents files?"
- return get_path (shellcon.CSIDL_PERSONAL)
-my_documents = personal_folder
-
-def recent ():
- "What folder holds the Documents shortcuts (from the Start Menu)?"
- return get_path (shellcon.CSIDL_RECENT)
-
-def sendto ():
- "What folder holds the SendTo shortcuts (from the Context Menu)?"
- return get_path (shellcon.CSIDL_SENDTO)
-
-def CreateShortcut (Path, Target, Arguments = "", StartIn = "", Icon = ("",0), Description = ""):
- """Create a Windows shortcut:
-
- Path - As what file should the shortcut be created?
- Target - What command should the desktop use?
- Arguments - What arguments should be supplied to the command?
- StartIn - What folder should the command start in?
- Icon - (filename, index) What icon should be used for the shortcut?
- Description - What description should the shortcut be given?
-
- eg
- CreateShortcut (
- Path=os.path.join (desktop (), "PythonI.lnk"),
- Target=r"c:\python\python.exe",
- Icon=(r"c:\python\python.exe", 0),
- Description="Python Interpreter"
- )
- """
- sh = pythoncom.CoCreateInstance (
- shell.CLSID_ShellLink,
- None,
- pythoncom.CLSCTX_INPROC_SERVER,
- shell.IID_IShellLink
- )
-
- sh.SetPath (Target)
- sh.SetDescription (Description)
- sh.SetArguments (Arguments)
- sh.SetWorkingDirectory (StartIn)
- sh.SetIconLocation (Icon[0], Icon[1])
-
- persist = sh.QueryInterface (pythoncom.IID_IPersistFile)
- persist.Save (Path, 1)
-
-if __name__ == '__main__':
- try:
- print 'Desktop =>', desktop ()
- print 'Common Desktop =>', desktop (1)
- print 'Application Data =>', application_data ()
- print 'Common Application Data =>', application_data (1)
- print 'Bookmarks =>', bookmarks ()
- print 'Common Bookmarks =>', bookmarks (1)
- print 'Start Menu =>', start_menu ()
- print 'Common Start Menu =>', start_menu (1)
- print 'Programs =>', programs ()
- print 'Common Programs =>', programs (1)
- print 'Startup =>', startup ()
- print 'Common Startup =>', startup (1)
- print 'My Documents =>', my_documents ()
- print 'Recent =>', recent ()
- print 'SendTo =>', sendto ()
- finally:
- raw_input ("Press enter...")
-
Deleted: pymoul/trunk/src/moul/osdependent/win32/processinfo.py
===================================================================
--- pymoul/trunk/src/moul/osdependent/win32/processinfo.py 2007-01-26 16:40:35 UTC (rev 84)
+++ pymoul/trunk/src/moul/osdependent/win32/processinfo.py 2007-01-26 17:37:52 UTC (rev 85)
@@ -1,34 +0,0 @@
-#http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/303339
-#Title: getting process information on windows
-#Submitter: John Nielsen (other recipes)
-#Last Updated: 2004/09/03
-#Version no: 1.0
-#Category: System
-
-import win32pdh, string, win32api
-
-def procids():
- #each instance is a process, you can have multiple processes w/same name
- junk, instances = win32pdh.EnumObjectItems(None,None,'process', win32pdh.PERF_DETAIL_WIZARD)
- proc_ids=[]
- proc_dict={}
- for instance in instances:
- if instance in proc_dict:
- proc_dict[instance] = proc_dict[instance] + 1
- else:
- proc_dict[instance]=0
- for instance, max_instances in proc_dict.items():
- for inum in xrange(max_instances+1):
- hq = win32pdh.OpenQuery() # initializes the query handle
- path = win32pdh.MakeCounterPath( (None,'process',instance, None, inum,'ID Process') )
- counter_handle=win32pdh.AddCounter(hq, path)
- win32pdh.CollectQueryData(hq) #collects data for the counter
- type, val = win32pdh.GetFormattedCounterValue(counter_handle, win32pdh.PDH_FMT_LONG)
- proc_ids.append((instance,str(val)))
- win32pdh.CloseQuery(hq)
-
- proc_ids.sort()
- return proc_ids
-
-
-print procids()
\ No newline at end of file
Deleted: pymoul/trunk/src/moul/osdependent/win32/wmi.py
===================================================================
--- pymoul/trunk/src/moul/osdependent/win32/wmi.py 2007-01-26 16:40:35 UTC (rev 84)
+++ pymoul/trunk/src/moul/osdependent/win32/wmi.py 2007-01-26 17:37:52 UTC (rev 85)
@@ -1,1246 +0,0 @@
-##
-# wmi - a lightweight Python wrapper around Microsoft's WMI interface
-#
-# Windows Management Instrumentation (WMI) is Microsoft's answer to
-# the DMTF's Common Information Model. It allows you to query just
-# about any conceivable piece of information from any computer which
-# is running the necessary agent and over which have you the
-# necessary authority.
-#
-# The implementation is by means of COM/DCOM and most of the examples
-# assume you're running one of Microsoft's scripting technologies.
-# Fortunately, Mark Hammond's pywin32 has pretty much all you need
-# for a workable Python adaptation. I haven't tried any of the fancier
-# stuff like Async calls and so on, so I don't know if they'd work.
-#
-# Since the COM implementation doesn't give much away to Python
-# programmers, I've wrapped it in some lightweight classes with
-# some getattr / setattr magic to ease the way. In particular:
-#
-# <ul>
-# <li>
-# The _wmi_namespace object itself will determine its classes
-# and allow you to return all instances of any of them by
-# using its name as an attribute. As an additional shortcut,
-# you needn't specify the Win32_; if the first lookup fails
-# it will try again with a Win32_ on the front:
-#
-# <pre class="code">
-# disks = wmi.WMI ().Win32_LogicalDisk ()
-# </pre>
-#
-# In addition, you can specify what would become the WHERE clause
-# as keyword parameters:
-#
-# <pre class="code">
-# fixed_disks = wmi.WMI ().Win32_LogicalDisk (DriveType = 3)
-# </pre>
-# </li>
-#
-# <li>
-# The objects returned by a WMI lookup are wrapped in a Python
-# class which determines their methods and classes and allows
-# you to access them as though they were Python classes. The
-# methods only allow named parameters.
-#
-# <pre class="code">
-# for p in wmi.WMI ().Win32_Process ():
-# if p.Name.lower () == 'notepad.exe':
-# p.Terminate (Result=1)
-# </pre>
-# </li>
-#
-# <li>
-# Doing a print on one of the WMI objects will result in its
-# GetObjectText_ method being called, which usually produces
-# a meaningful printout of current values.
-# The repr of the object will include its full WMI path,
-# which lets you get directly to it if you need to.
-# </li>
-#
-# <li>
-# You can get the associators and references of an object as
-# a list of python objects by calling the associators () and
-# references () methods on a WMI Python object.
-# NB Don't do this on a Win32_ComputerSystem object; it will
-# take all day and kill your machine!
-#
-# <pre class="code">
-# for p in wmi.WMI ().Win32_Process ():
-# if p.Name.lower () == 'notepad.exe':
-# for r in p.references ():
-# print r.Name
-# </pre>
-# </li>
-#
-# <li>
-# WMI classes (as opposed to instances) are first-class
-# objects, so you can get hold of a class, and call
-# its methods or set up a watch against it.
-#
-# <pre class="code">
-# process = wmi.WMI ().Win32_Process
-# process.Create (CommandLine="notepad.exe")
-# </pre>
-#
-# </li>
-#
-# <li>
-# To make it easier to use in embedded systems and py2exe-style
-# executable wrappers, the module will not force early Dispatch.
-# To do this, it uses a handy hack by Thomas Heller for easy access
-# to constants.
-# </li>
-#
-# <li>
-# Typical usage will be:
-#
-# <pre class="code">
-# import wmi
-#
-# vodev1 = wmi.WMI ("vodev1")
-# for disk in vodev1.Win32_LogicalDisk ():
-# if disk.DriveType == 3:
-# space = 100 * long (disk.FreeSpace) / long (disk.Size)
-# print "%s has %d%% free" % (disk.Name, space)
-# </pre>
-# </li>
-#
-# </ul>
-#
-# Many thanks, obviously to Mark Hammond for creating the win32all
-# extensions, but also to Alex Martelli and Roger Upole, whose
-# c.l.py postings pointed me in the right direction.
-# Thanks especially in release 1.2 to Paul Tiemann for his code
-# contributions and robust testing.
-#
-# (c) Tim Golden - mail at timgolden.me.uk 5th June 2003
-# Licensed under the (GPL-compatible) MIT License:
-# http://www.opensource.org/licenses/mit-license.php
-#
-# For change history see CHANGELOG.TXT
-##
-try:
- True, False
-except NameError:
- True = 1
- False = 0
-
-try:
- object
-except NameError:
- class object: pass
-
-__VERSION__ = "1.2.1"
-
-_DEBUG = False
-
-import sys
-import re
-from win32com.client import GetObject, Dispatch
-import pywintypes
-
-class ProvideConstants (object):
- """
- A class which, when called on a win32com.client.Dispatch object,
- provides lazy access to constants defined in the typelib.
-
- They can be accessed as attributes of the _constants property.
- From Thomas Heller on c.l.py
- """
- def __init__(self, comobj):
- "@param comobj A COM object whose typelib constants are to be exposed"
- comobj.__dict__["_constants"] = self
- # Get the typelibrary's typecomp interface
- self.__typecomp = \
- comobj._oleobj_.GetTypeInfo().GetContainingTypeLib()[0].GetTypeComp()
-
- def __getattr__(self, name):
- if name.startswith("__") and name.endswith("__"):
- raise AttributeError, name
- result = self.__typecomp.Bind(name)
- # Bind returns a 2-tuple, first item is TYPEKIND,
- # the second item has the value
- if not result[0]:
- raise AttributeError, name
- return result[1].value
-
-obj = GetObject ("winmgmts:")
-ProvideConstants (obj)
-
-wbemErrInvalidQuery = obj._constants.wbemErrInvalidQuery
-wbemErrTimedout = obj._constants.wbemErrTimedout
-wbemFlagReturnImmediately = obj._constants.wbemFlagReturnImmediately
-wbemFlagForwardOnly = obj._constants.wbemFlagForwardOnly
-
-def handle_com_error (error_info):
- """Convenience wrapper for displaying all manner of COM errors.
- Raises a x_wmi exception with more useful information attached
-
- @param error_info The structure attached to a pywintypes.com_error
- """
- hresult_code, hresult_name, additional_info, parameter_in_error = error_info
- exception_string = ["%s - %s" % (hex (hresult_code), hresult_name)]
- if additional_info:
- wcode, source_of_error, error_description, whlp_file, whlp_context, scode = additional_info
- exception_string.append (" Error in: %s" % source_of_error)
- exception_string.append (" %s - %s" % (hex (scode), error_description.strip ()))
- raise x_wmi, "\n".join (exception_string)
-
-def from_time (year=None, month=None, day=None, hours=None, minutes=None, seconds=None, microseconds=None, timezone=None):
- """
- Convenience wrapper to take a series of date/time elements and return a WMI time
- of the form yyyymmddHHMMSS.mmmmmm+UUU. All elements may be int, string or
- omitted altogether. If omitted, they will be replaced in the output string
- by a series of stars of the appropriate length.
-
- @param year The year element of the date/time
- @param month The month element of the date/time
- @param day The day element of the date/time
- @param hours The hours element of the date/time
- @param minutes The minutes element of the date/time
- @param seconds The seconds element of the date/time
- @param microseconds The microseconds element of the date/time
- @param timezone The timeezone element of the date/time
-
- @return A WMI datetime string of the form: yyyymmddHHMMSS.mmmmmm+UUU
- """
- def str_or_stars (i, length):
- if i is None:
- return "*" * length
- else:
- return str (i).rjust (length, "0")
-
- wmi_time = ""
- wmi_time += str_or_stars (year, 4)
- wmi_time += str_or_stars (month, 2)
- wmi_time += str_or_stars (day, 2)
- wmi_time += str_or_stars (hours, 2)
- wmi_time += str_or_stars (minutes, 2)
- wmi_time += str_or_stars (seconds, 2)
- wmi_time += "."
- wmi_time += str_or_stars (microseconds, 6)
- wmi_time += str_or_stars (timezone, 4)
-
- return wmi_time
-
-def to_time (wmi_time):
- """
- Convenience wrapper to take a WMI datetime string of the form
- yyyymmddHHMMSS.mmmmmm+UUU and return a 9-tuple containing the
- individual elements, or None where string contains placeholder
- stars.
-
- @param wmi_time The WMI datetime string in yyyymmddHHMMSS.mmmmmm+UUU format
-
- @return A 9-tuple of (year, month, day, hours, minutes, seconds, microseconds, timezone)
- """
- def int_or_none (s, start, end):
- try:
- return int (s[start:end])
- except ValueError:
- return None
-
- year = int_or_none (wmi_time, 0, 4)
- month = int_or_none (wmi_time, 4, 6)
- day = int_or_none (wmi_time, 6, 8)
- hours = int_or_none (wmi_time, 8, 10)
- minutes = int_or_none (wmi_time, 10, 12)
- seconds = int_or_none (wmi_time, 12, 14)
- microseconds = int_or_none (wmi_time, 15, 21)
- timezone = wmi_time[21:]
-
- return year, month, day, hours, minutes, seconds, microseconds, timezone
-
-#
-# Exceptions
-#
-class x_wmi (Exception):
- pass
-
-class x_wmi_invalid_query (x_wmi):
- pass
-
-class x_wmi_timed_out (x_wmi):
- pass
-
-class x_wmi_no_namespace (x_wmi):
- pass
-
-WMI_EXCEPTIONS = {
- wbemErrInvalidQuery : x_wmi_invalid_query,
- wbemErrTimedout : x_wmi_timed_out
-}
-
-def _set (obj, attribute, value):
- """
- Helper function to add an attribute directly into the instance
- dictionary, bypassing possible __getattr__ calls
-
- @param obj Any python object
- @param attribute String containing attribute name
- @param value Any python object
- """
- obj.__dict__[attribute] = value
-
-class _wmi_method:
- """
- A currying sort of wrapper around a WMI method name. It
- abstract's the method's parameters and can be called like
- a normal Python object passing in the parameter values.
-
- Output parameters are returned from the call as a tuple.
- In addition, the docstring is set up as the method's
- signature, including an indication as to whether any
- given parameter is expecting an array, and what
- special privileges are required to call the method.
- """
-
- def __init__ (self, ole_object, method_name):
- """
- @param ole_object The WMI class/instance whose method is to be called
- @param method_name The name of the method to be called
- """
- try:
- self.ole_object = Dispatch (ole_object)
- self.method = ole_object.Methods_ (method_name)
- self.qualifiers = {}
- for q in self.method.Qualifiers_:
- self.qualifiers[q.Name] = q.Value
- self.provenance = "\n".join (self.qualifiers.get ("MappingStrings", []))
-
- self.in_parameters = self.method.InParameters
- self.out_parameters = self.method.OutParameters
- if self.in_parameters is None:
- self.in_parameter_names = []
- else:
- self.in_parameter_names = [(i.Name, i.IsArray) for i in self.in_parameters.Properties_]
- if self.out_parameters is None:
- self.out_parameter_names = []
- else:
- self.out_parameter_names = [(i.Name, i.IsArray) for i in self.out_parameters.Properties_]
-
- doc = "%s (%s) => (%s)" % (
- method_name,
- ", ".join ([name + ("", "[]")[is_array] for (name, is_array) in self.in_parameter_names]),
- ", ".join ([name + ("", "[]")[is_array] for (name, is_array) in self.out_parameter_names])
- )
- privileges = self.qualifiers.get ("Privileges", [])
- if privileges:
- doc += " | Needs: " + ", ".join (privileges)
- self.__doc__ = doc
- except pywintypes.com_error, error_info:
- handle_com_error (error_info)
-
- def __call__ (self, **kwargs):
- """
- Execute the call to a WMI method, returning
- a tuple (even if is of only one value) containing
- the out and return parameters.
- """
- try:
- if self.in_parameters:
- parameter_names = {}
- for name, is_array in self.in_parameter_names:
- parameter_names[name] = is_array
-
- parameters = self.in_parameters
- for k, v in kwargs.items ():
- is_array = parameter_names.get (k)
- if is_array is None:
- raise AttributeError, "%s is not a valid parameter for %s" % (k, self.__doc__)
- else:
- if is_array:
- try: list (v)
- except TypeError: raise TypeError, "%s must be iterable" % k
-
- parameters.Properties_ (k).Value = v
-
- result = self.ole_object.ExecMethod_ (self.method.Name, self.in_parameters)
- else:
- result = self.ole_object.ExecMethod_ (self.method.Name)
-
- results = []
- for name, is_array in self.out_parameter_names:
- value = result.Properties_ (name).Value
- if is_array:
- #
- # Thanks to Jonas Bjering for bug report and path
- #
- results.append (list (value or []))
- else:
- results.append (value)
- return tuple (results)
-
- except pywintypes.com_error, error_info:
- handle_com_error (error_info)
-
- def __repr__ (self):
- return "<function %s>" % self.__doc__
-
-#
-# class _wmi_object
-#
-class _wmi_object:
- "A lightweight wrapper round an OLE WMI object"
-
- def __init__ (self, ole_object, instance_of=None, fields=[]):
- try:
- _set (self, "ole_object", ole_object)
- _set (self, "_instance_of", instance_of)
- _set (self, "properties", {})
- _set (self, "methods", {})
-
- if self._instance_of:
- if fields:
- for field in fields:
- self.properties[field] = None
- else:
- _set (self, "properties", self._instance_of.properties.copy ())
- _set (self, "methods", self._instance_of.methods)
- else:
- for p in ole_object.Properties_:
- self.properties[p.Name] = None
- for m in ole_object.Methods_:
- self.methods[m.Name] = None
-
- _set (self, "_properties", self.properties.keys ())
- _set (self, "_methods", self.methods.keys ())
-
- _set (self, "qualifiers", {})
- for q in self.ole_object.Qualifiers_:
- self.qualifiers[q.Name] = q.Value
- _set (self, "is_association", self.qualifiers.has_key ("Association"))
-
- except pywintypes.com_error, error_info:
- handle_com_error (error_info)
-
- def __str__ (self):
- """
- For a call to print [object] return the OLE description
- of the properties / values of the object
- """
- try:
- return self.ole_object.GetObjectText_ ()
- except pywintypes.com_error, error_info:
- handle_com_error (error_info)
-
- def __repr__ (self):
- """
- Indicate both the fact that this is a wrapped WMI object
- and the WMI object's own identifying class.
- """
- try:
- return "<%s: %s>" % (self.__class__.__name__, str (self.Path_.Path))
- except pywintypes.com_error, error_info:
- handle_com_error (error_info)
-
- def _cached_properties (self, attribute):
- if self.properties[attribute] is None:
- self.properties[attribute] = self.ole_object.Properties_ (attribute)
- return self.properties[attribute]
-
- def _cached_methods (self, attribute):
- if self.methods[attribute] is None:
- self.methods[attribute] = _wmi_method (self.ole_object, attribute)
- return self.methods[attribute]
-
- def __getattr__ (self, attribute):
- """
- Attempt to pass attribute calls to the proxied COM object.
- If the attribute is recognised as a property, return its value;
- if it is recognised as a method, return a method wrapper which
- can then be called with parameters; otherwise pass the lookup
- on to the underlying object.
- """
- try:
- if self.properties.has_key (attribute):
- value = self._cached_properties (attribute).Value
- #
- # If this is an association, its properties are
- # actually the paths to the two aspects of the
- # association, so translate them automatically
- # into WMI objects.
- #
- if self.is_association:
- return WMI (moniker=value)
- else:
- return value
- elif self.methods.has_key (attribute):
- return self._cached_methods (attribute)
- else:
- return getattr (self.ole_object, attribute)
- except pywintypes.com_error, error_info:
- handle_com_error (error_info)
-
- def __setattr__ (self, attribute, value):
- """
- If the attribute to be set is valid for the proxied
- COM object, set that objects's parameter value; if not,
- raise an exception.
- """
- try:
- if self.properties.has_key (attribute):
- self._cached_properties (attribute).Value = value
- if self.ole_object.Path_.Path:
- self.ole_object.Put_ ()
- else:
- raise AttributeError, attribute
- except pywintypes.com_error, error_info:
- handle_com_error (error_info)
-
- def __eq__ (self, other):
- """
- Use WMI's CompareTo_ to compare this object with
- another. Don't try to do anything if the other
- object is not a wmi object. It might be possible
- to compare this object's unique key with a string
- or something, but this doesn't seem to be universal
- enough to merit a special case.
- """
- if isinstance (other, self.__class__):
- return self.ole_object.CompareTo_ (other.ole_object)
- else:
- raise x_wmi, "Can't compare a WMI object with something else"
-
- def put (self):
- self.ole_object.Put_ ()
-
- def set (self, **kwargs):
- """
- Set several properties of the underlying object
- at one go. This is particularly useful in combination
- with the new () method below. However, an instance
- which has been spawned in this way won't have enough
- information to write pack, so only try if the
- instance has a path.
- """
- if kwargs:
- try:
- for attribute, value in kwargs.items ():
- if self.properties.has_key (attribute):
- self._cached_properties (attribute).Value = value
- else:
- raise AttributeError, attribute
- #
- # Only try to write the attributes
- # back if the object exists.
- #
- if self.ole_object.Path_.Path:
- self.ole_object.Put_ ()
- except pywintypes.com_error, error_info:
- handle_com_error (error_info)
-
- def path (self):
- """
- Return the WMI URI to this object. Can be used to
- determine the path relative to the parent namespace. eg,
-
- <pre class="code">
- pp0 = wmi.WMI ().Win32_ParallelPort ()[0]
- print pp0.path ().RelPath
- </pre>
- """
- try:
- return self.ole_object.Path_
- except pywintypes.com_error, error_info:
- handle_com_error (error_info)
-
- def derivation (self):
- """Return a tuple representing the object derivation for
- this object, with the most specific object first. eg,
-
- pp0 = wmi.WMI ().Win32_ParallelPort ()[0]
- print ' <- '.join (pp0.derivation ())
- """
- try:
- return self.ole_object.Derivation_
- except pywintypes.com_error, error_info:
- handle_com_error (error_info)
-
- def associators (self, wmi_association_class="", wmi_result_class=""):
- """Return a list of objects related to this one, optionally limited
- either by association class (ie the name of the class which relates
- them) or by result class (ie the name of the class which would be
- retrieved)
-
- <pre class="code">
-c = wmi.WMI ()
-pp = c.Win32_ParallelPort ()[0]
-
-for i in pp.associators (wmi_association_class="Win32_PortResource"):
- print i
-
-for i in pp.associators (wmi_result_class="Win32_PnPEntity"):
- print i
- </pre>
- """
- try:
- return [
- _wmi_object (i) for i in \
- self.ole_object.Associators_ (
- strAssocClass=wmi_association_class,
- strResultClass=wmi_result_class
- )
- ]
- except pywintypes.com_error, error_info:
- handle_com_error (error_info)
-
- def references (self, wmi_class=""):
- """Return a list of associations involving this object, optionally
- limited by the result class (the name of the association class).
-
- NB Associations are treated specially; although WMI only returns
- the string corresponding to the instance of each associated object,
- this module will automatically convert that to the object itself.
-
- <pre class="code">
- c = wmi.WMI ()
- sp = c.Win32_SerialPort ()[0]
-
- for i in sp.references ():
- print i
-
- for i in sp.references (wmi_class="Win32_SerialPortSetting"):
- print i
- </pre>
- """
- try:
- return [_wmi_object (i) for i in self.ole_object.References_ (strResultClass=wmi_class)]
- except pywintypes.com_error, error_info:
- handle_com_error (error_info)
-
-#
-# class _wmi_class
-#
-class _wmi_class (_wmi_object):
- """Currying class to assist in issuing queries against
- a WMI namespace. The idea is that when someone issues
- an otherwise unknown method against the WMI object, if
- it matches a known WMI class a query object will be
- returned which may then be called with one or more params
- which will form the WHERE clause. eg,
-
- <pre class="code">
- c = wmi.WMI ()
- c_drive = c.Win32_LogicalDisk (Name='C:')
- </pre>
- """
- def __init__ (self, namespace, wmi_class):
- _wmi_object.__init__ (self, wmi_class)
- _set (self, "_namespace", namespace)
- _set (self, "_class_name", wmi_class.Path_.Class)
-
- def query (self, fields=[], **where_clause):
- """Make it slightly easier to query against the class,
- by calling the namespace's query with the class preset.
- Won't work if the class has been instantiated directly.
- """
- if self._namespace is None:
- raise x_wmi_no_namespace, "You cannot query directly from a WMI class"
-
- try:
- field_list = ", ".join (fields) or "*"
- wql = "SELECT " + field_list + " FROM " + self._class_name
- if where_clause:
- wql += " WHERE " + " AND ". join (["%s = '%s'" % (k, v) for k, v in where_clause.items ()])
- return self._namespace.query (wql, self, fields)
- except pywintypes.com_error, error_info:
- handle_com_error (error_info)
-
- __call__ = query
-
- def watch_for (
- self,
- notification_type=None,
- delay_secs=1,
- **where_clause
- ):
- if self._namespace is None:
- raise x_wmi_no_namespace, "You cannot watch directly from a WMI class"
-
- return self._namespace.watch_for (
- notification_type=notification_type,
- wmi_class=self._class_name,
- delay_secs=delay_secs,
- **where_clause
- )
-
- def instances (self):
- """Return a list of instances of the WMI class
- """
- try:
- return [_wmi_object (instance, self) for instance in self.Instances_ ()]
- except pywintypes.com_error, error_info:
- handle_com_error (error_info)
-
- def new (self, **kwargs):
- """This is the equivalent to the raw-WMI SpawnInstance_
- method. Note that there are relatively few uses for
- this, certainly fewer than you might imagine. Most
- classes which need to create a new *real* instance
- of themselves, eg Win32_Process, offer a .Create
- method. SpawnInstance_ is generally reserved for
- instances which are passed as parameters to such
- .Create methods, a common example being the
- Win32_SecurityDescriptor, passed to Win32_Share.Create
- and other instances which need security.
-
- The example here is Win32_ProcessStartup, which
- controls the shown/hidden state etc. of a new
- Win32_Process instance.
-
- <pre class="code">
- import win32con
- import wmi
- c = wmi.WMI ()
- startup = c.Win32_ProcessStartup.new (ShowWindow=win32con.SW_SHOWMINIMIZED)
- pid, retval = c.Win32_Process.Create (
- CommandLine="notepad.exe",
- ProcessStartupInformation=startup
- )
- </pre>
-
- NB previous versions of this module, used this function
- to create new process. This is *not* a good example
- of its use; it is better handled with something like
- the example above.
- """
- try:
- obj = _wmi_object (self.SpawnInstance_ (), self)
- obj.set (**kwargs)
- return obj
- except pywintypes.com_error, error_info:
- handle_com_error (error_info)
-
-#
-# class _wmi_result
-#
-class _wmi_result:
- """Simple, data only result for targeted WMI queries which request
- data only result classes via fetch_as_classes.
- """
- def __init__(self, obj, attributes):
- if attributes:
- for attr in attributes:
- self.__dict__[attr] = obj.Properties_ (attr).Value
- else:
- for p in obj.Properties_:
- attr = p.Name
- self.__dict__[attr] = obj.Properties_(attr).Value
-
-#
-# class WMI
-#
-class _wmi_namespace:
- """A WMI root of a computer system. The classes attribute holds a list
- of the classes on offer. This means you can explore a bit with
- things like this:
-
- <pre class="code">
- c = wmi.WMI ()
- for i in c.classes:
- if "user" in i.lower ():
- print i
- </pre>
- """
- def __init__ (self, namespace, find_classes):
- _set (self, "_namespace", namespace)
- #
- # wmi attribute preserved for backwards compatibility
- #
- _set (self, "wmi", namespace)
-
- # Initialise the "classes" attribute, to avoid infinite recursion in the
- # __getattr__ method (which uses it).
- self.classes = {}
- #
- # Pick up the list of classes under this namespace
- # so that they can be queried, and used as though
- # properties of the namespace by means of the __getattr__
- # hook below.
- # If the namespace does not support SubclassesOf, carry on
- # regardless
- #
- if find_classes:
- try:
- self.classes.update (self.subclasses_of ())
- except AttributeError:
- pass
-
- def __repr__ (self):
- return "<_wmi_namespace: %s>" % self.wmi
-
- def __str__ (self):
- return repr (self)
-
- def get (self, moniker):
- try:
- return _wmi_object (self.wmi.Get (moniker))
- except pywintypes.com_error, error_info:
- handle_com_error (error_info)
-
- def handle (self):
- """The raw OLE object representing the WMI namespace"""
- return self._namespace
-
- def subclasses_of (self, root="", regex=r".*"):
- classes = {}
- for c in self._namespace.SubclassesOf (root):
- klass = c.Path_.Class
- if re.match (regex, klass):
- classes[klass] = None
- return classes
-
- def instances (self, class_name):
- """Return a list of instances of the WMI class. This is
- (probably) equivalent to querying with no qualifiers.
-
- <pre class="code">
- system.instances ("Win32_LogicalDisk")
- # should be the same as
- system.Win32_LogicalDisk ()
- </pre>
- """
- try:
- return [_wmi_object (obj) for obj in self._namespace.InstancesOf (class_name)]
- except pywintypes.com_error, error_info:
- handle_com_error (error_info)
-
- def new (self, wmi_class, **kwargs):
- """This is now implemented by a call to _wmi_namespace.new (qv)"""
- return getattr (self, wmi_class).new (**kwargs)
-
- new_instance_of = new
-
- def _raw_query (self, wql):
- """Execute a WQL query and return its raw results. Use the flags
- recommended by Microsoft to achieve a read-only, semi-synchronous
- query where the time is taken while looping through. Should really
- be a generator, but ...
- NB Backslashes need to be doubled up.
- """
- flags = wbemFlagReturnImmediately | wbemFlagForwardOnly
- wql = wql.replace ("\\", "\\\\")
- if _DEBUG: print "_raw_query(wql):", wql
- try:
- return self._namespace.ExecQuery (strQuery=wql, iFlags=flags)
- except pywintypes.com_error, (hresult, hresult_text, additional, param_in_error):
- raise WMI_EXCEPTIONS.get (hresult, x_wmi (hresult))
-
- def query (self, wql, instance_of=None, fields=[]):
- """Perform an arbitrary query against a WMI object, and return
- a list of _wmi_object representations of the results.
- """
- return [ _wmi_object (obj, instance_of, fields) for obj in self._raw_query(wql) ]
-
- def fetch_as_classes (self, wmi_classname, fields=(), **where_clause):
- """Build and execute a wql query to fetch the specified list of fields from
- the specified wmi_classname + where_clause, then return the results as
- a list of simple class instances with attributes matching fields_list.
-
- If fields is left empty, select * and pre-load all class attributes for
- each class returned.
- """
- wql = "SELECT %s FROM %s" % (fields and ", ".join (fields) or "*", wmi_classname)
- if where_clause:
- wql += " WHERE " + " AND ".join (["%s = '%s'" % (k, v) for k, v in where_clause.items()])
- return [_wmi_result (obj, fields) for obj in self._raw_query(wql)]
-
- def fetch_as_lists (self, wmi_classname, fields, **where_clause):
- """Build and execute a wql query to fetch the specified list of fields from
- the specified wmi_classname + where_clause, then return the results as
- a list of lists whose values correspond fields_list.
- """
- wql = "SELECT %s FROM %s" % (", ".join (fields), wmi_classname)
- if where_clause:
- wql += " WHERE " + " AND ".join (["%s = '%s'" % (k, v) for k, v in where_clause.items()])
- results = []
- for obj in self._raw_query(wql):
- results.append ([obj.Properties_ (field).Value for field in fields])
- return results
-
- def watch_for (
- self,
- raw_wql=None,
- notification_type=None,
- wmi_class=None,
- delay_secs=1,
- **where_clause
- ):
- """Set up an event tracker on a WMI event. This function
- returns an wmi_watcher which can be called to get the
- next event. eg,
-
- <pre class="code">
- c = wmi.WMI ()
-
- raw_wql = "SELECT * FROM __InstanceCreationEvent WITHIN 2 WHERE TargetInstance ISA 'Win32_Process'"
- watcher = c.watch_for (raw_wql=raw_wql)
- while 1:
- process_created = watcher ()
- print process_created.Name
-
- # or
-
- watcher = c.watch_for (
- notification_type="Creation",
- wmi_class="Win32_Process",
- delay_secs=2,
- Name='calc.exe'
- )
- calc_created = watcher ()
- </pre>
-
- Now supports timeout on the call to watcher, eg:
-
- <pre class="code">
- import pythoncom
- import wmi
- c = wmi.WMI (privileges=["Security"])
- watcher1 = c.watch_for (
- notification_type="Creation",
- wmi_class="Win32_NTLogEvent",
- Type="error"
- )
- watcher2 = c.watch_for (
- notification_type="Creation",
- wmi_class="Win32_NTLogEvent",
- Type="warning"
- )
-
- while 1:
- try:
- error_log = watcher1 (500)
- except wmi.x_wmi_timed_out:
- pythoncom.PumpWaitingMessages ()
- else:
- print error_log
-
- try:
- warning_log = watcher2 (500)
- except wmi.x_wmi_timed_out:
- pythoncom.PumpWaitingMessages ()
- else:
- print warning_log
- </pre>
- """
- class_name = wmi_class
- if raw_wql:
- wql = raw_wql
- else:
- if where_clause:
- where = " AND " + " AND ".join (["TargetInstance.%s = '%s'" % (k, v) for k, v in where_clause.items ()])
- else:
- where = ""
- wql = \
- "SELECT * FROM __Instance%sEvent WITHIN %d WHERE TargetInstance ISA '%s' %s" % \
- (notification_type, delay_secs, class_name, where)
-
- if _DEBUG: print wql
-
- try:
- return _wmi_watcher (self._namespace.ExecNotificationQuery (wql))
- except pywintypes.com_error, error_info:
- handle_com_error (error_info)
-
- def __getattr__ (self, attribute):
- """Offer WMI classes as simple attributes. Pass through any untrapped
- unattribute to the underlying OLE object. This means that new or
- unmapped functionality is still available to the module user.
- """
- #
- # Don't try to match against known classes as was previously
- # done since the list may not have been requested
- # (find_classes=False).
- #
- try:
- return self._cached_classes (attribute)
- except pywintypes.com_error, error_info:
- try:
- return self._cached_classes ("Win32_" + attribute)
- except pywintypes.com_error, error_info:
- return getattr (self._namespace, attribute)
-
- def _cached_classes (self, class_name):
- """Standard caching helper which keeps track of classes
- already retrieved by name and returns the existing object
- if found. If this is the first retrieval, store it and
- pass it back
- """
- if self.classes.get (class_name) is None:
- self.classes[class_name] = _wmi_class (self, self._namespace.Get (class_name))
- return self.classes[class_name]
-
-#
-# class _wmi_watcher
-#
-class _wmi_watcher:
- """Helper class for WMI.watch_for below (qv)"""
-
- def __init__ (self, wmi_event):
- self.wmi_event = wmi_event
-
- def __call__ (self, timeout_ms=-1):
- """When called, return the instance which caused the event. Supports
- timeout in milliseconds (defaulting to infinite). If the watcher
- times out, x_wmi_timed_out is raised. This makes it easy to support
- watching for multiple objects.
- """
- try:
- return _wmi_object (self.wmi_event.NextEvent (timeout_ms).Properties_ ("TargetInstance").Value)
- except pywintypes.com_error, error_info:
- hresult_code, hresult_name, additional_info, parameter_in_error = error_info
- if additional_info:
- wcode, source_of_error, error_description, whlp_file, whlp_context, scode = additional_info
- if scode == wbemErrTimedout:
- raise x_wmi_timed_out
- handle_com_error (error_info)
-
-PROTOCOL = "winmgmts:"
-IMPERSONATION_LEVEL = "impersonate"
-AUTHENTICATION_LEVEL = "default"
-NAMESPACE = "root/cimv2"
-def connect (
- computer=".",
- impersonation_level="",
- authentication_level="",
- authority="",
- privileges="",
- moniker="",
- wmi=None,
- namespace="",
- suffix="",
- user="",
- password="",
- find_classes=True,
- debug=False
-):
- """The WMI constructor can either take a ready-made moniker or as many
- parts of one as are necessary. Eg,
-
- <pre class="code">
- c = wmi.WMI (moniker="winmgmts:{impersonationLevel=Delegate}//remote")
-
- # or
-
- c = wmi.WMI (computer="remote", privileges=["!RemoteShutdown", "Security"])
- </pre>
-
- I daren't link to a Microsoft URL; they change so often. Try Googling for
- WMI construct moniker and see what it comes back with.
-
- For complete control, a named argument "wmi" can be supplied, which
- should be a SWbemServices object, which you create yourself. Eg,
-
- <pre class="code">
- loc = win32com.client.Dispatch("WbemScripting.SWbemLocator")
- svc = loc.ConnectServer(...)
- c = wmi.WMI(wmi=svc)
- </pre>
-
- This is the only way of connecting to a remote computer with a different
- username, as the moniker syntax does not allow specification of a user
- name.
-
- If the "wmi" parameter is supplied, all other parameters are ignored.
- """
- global _DEBUG
- _DEBUG = debug
-
- #
- # If namespace is a blank string, leave
- # it unaltered as it might to trying to
- # access the root namespace
- #
- #if namespace is None:
- # namespace = NAMESPACE
-
- try:
- if wmi:
- obj = wmi
-
- elif moniker:
- if not moniker.startswith (PROTOCOL):
- moniker = PROTOCOL + moniker
- if _DEBUG: print moniker
- obj = GetObject (moniker)
-
- else:
- if user:
- if impersonation_level or authentication_level or privileges or suffix:
- raise x_wmi, "You can't specify an impersonation, authentication or privilege as well as a username"
- else:
- obj = connect_server (
- server=computer,
- namespace=namespace,
- user=user,
- password=password,
- authority=authority
- )
-
- else:
- moniker = construct_moniker (
- computer=computer,
- impersonation_level=impersonation_level or IMPERSONATION_LEVEL,
- authentication_level=authentication_level or AUTHENTICATION_LEVEL,
- authority=authority,
- privileges=privileges,
- namespace=namespace,
- suffix=suffix
- )
- if _DEBUG: print moniker
- obj = GetObject (moniker)
-
- wmi_type = get_wmi_type (obj)
-
- if wmi_type == "namespace":
- return _wmi_namespace (obj, find_classes)
- elif wmi_type == "class":
- return _wmi_class (None, obj)
- elif wmi_type == "instance":
- return _wmi_object (obj)
- else:
- raise x_wmi, "Unknown moniker type"
-
- except pywintypes.com_error, error_info:
- handle_com_error (error_info)
-
-WMI = connect
-
-def construct_moniker (
- computer=None,
- impersonation_level="Impersonate",
- authentication_level="Default",
- authority=None,
- privileges=None,
- namespace=None,
- suffix=None
-):
- security = []
- if impersonation_level: security.append ("impersonationLevel=%s" % impersonation_level)
- if authentication_level: security.append ("authenticationLevel=%s" % authentication_level)
- #
- # Use of the authority descriptor is invalid on the local machine
- #
- if authority and computer: security.append ("authority=%s" % authority)
- if privileges: security.append ("(%s)" % ", ".join (privileges))
-
- moniker = [PROTOCOL]
- if security: moniker.append ("{%s}/" % ",".join (security))
- if computer: moniker.append ("/%s/" % computer)
- if namespace:
- parts = re.split (r"[/\\]", namespace)
- if parts[0] != 'root':
- parts.insert (0, "root")
- moniker.append ("/".join (parts))
- if suffix: moniker.append (":%s" % suffix)
- return "".join (moniker)
-
-def get_wmi_type (obj):
- try:
- path = obj.Path_
- except AttributeError:
- return "namespace"
- else:
- if path.IsClass:
- return "class"
- else:
- return "instance"
-
-def connect_server (
- server,
- namespace = "",
- user = "",
- password = "",
- locale = "",
- authority = "",
- security_flags = 0,
- named_value_set = None
-):
- """Return a remote server running WMI
-
- server - name of the server
- namespace - namespace to connect to: defaults to whatever's defined as default
- user - username to connect as, either local or domain (dom\name or user@domain for XP)
- password: leave blank to use current context
- locale: desired locale in form MS_XXXX (eg MS_409 for Am En)
- authority: either "Kerberos:" or an NT domain. Not needed if included in user
- security_flags: if 0, connect will wait forever; if 0x80, connect will timeout at 2 mins
- named_value_set: typically empty, otherwise a context-specific SWbemNamedValueSet
-
- <pre class="code">
- c = wmi.WMI (wmi=wmi.connect_server (server="remote_machine", user="myname", password="mypassword"))
- </pre>
- """
- if _DEBUG:
- print server
- print namespace
- print user
- print password
- print locale
- print authority
- print security_flags
- print named_value_set
-
- return Dispatch ("WbemScripting.SWbemLocator").\
- ConnectServer (
- server,
- namespace,
- user,
- password,
- locale,
- authority,
- security_flags,
- named_value_set
- )
-
-def Registry (
- computer=None,
- impersonation_level="Impersonate",
- authentication_level="Default",
- authority=None,
- privileges=None,
- moniker=None
-):
-
- if not moniker:
- moniker = construct_moniker (
- computer=computer,
- impersonation_level=impersonation_level,
- authentication_level=authentication_level,
- authority=authority,
- privileges=privileges,
- namespace="default",
- suffix="StdRegProv"
- )
-
- try:
- return _wmi_object (GetObject (moniker))
-
- except pywintypes.com_error, error_info:
- handle_com_error (error_info)
-
-#
-# From a post to python-win32 by Sean
-#
-def machines_in_domain (domain_name):
- adsi = Dispatch ("ADsNameSpaces")
- nt = adsi.GetObject ("","WinNT:")
- result = nt.OpenDSObject ("WinNT://%s" % domain_name, "", "", 0)
- result.Filter = ["computer"]
- domain = []
- for machine in result:
- domain.append (machine.Name)
- return domain
-
-#
-# Typical use test
-#
-if __name__ == '__main__':
- system = WMI ()
- for my_computer in system.Win32_ComputerSystem ():
- print "Disks on", my_computer.Name
- for disk in system.Win32_LogicalDisk ():
- print disk.Caption, disk.Description, disk.ProviderName or ""
-
Modified: pymoul/trunk/src/moul/qt/mainwindow.py
===================================================================
--- pymoul/trunk/src/moul/qt/mainwindow.py 2007-01-26 16:40:35 UTC (rev 84)
+++ pymoul/trunk/src/moul/qt/mainwindow.py 2007-01-26 17:37:52 UTC (rev 85)
@@ -86,7 +86,7 @@
self._moulrunning_thread = MoulRunningThread()
self.connect(self._moulrunning_thread, SIGNAL('moulIsRunning(bool)'),
self.on_moulIsRunning)
- self._moulrunning_thread.startChecker(10.0) # check now and every 10 seconds
+ self._moulrunning_thread.startChecker(5.0) # check now and every 5 seconds
@signalLogDecorator(LOG)
def on_moulIsRunning(self, bool):
@@ -569,7 +569,7 @@
def run(self):
while True:
- result = True #isMoulRunning()
+ result = isMoulRunning()
if result:
self.emit(SIGNAL('moulIsRunning(bool)'), True)
else:
Modified: pymoul/trunk/src/moul/qt/moulqt.py
===================================================================
--- pymoul/trunk/src/moul/qt/moulqt.py 2007-01-26 16:40:35 UTC (rev 84)
+++ pymoul/trunk/src/moul/qt/moulqt.py 2007-01-26 17:37:52 UTC (rev 85)
@@ -43,12 +43,12 @@
"""An instance of pyMoul QT is already running!""")
mb.exec_()
sys.exit(1)
- #if isMoulRunning():
- # mb = criticalMessageBox(app,
- # "URU is running",
- # """URU is running! Please close Uru or Uru Launcher first.""")
- # mb.exec_()
- # sys.exit(2)
+ if isMoulRunning():
+ mb = criticalMessageBox(app,
+ "URU is running",
+ """URU is running! Please close Uru or Uru Launcher first.""")
+ mb.exec_()
+ sys.exit(2)
mainWindow = MainWindow()
mainWindow.show()
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <ti...@us...> - 2007-01-26 16:40:36
|
Revision: 84
http://pymoul.svn.sourceforge.net/pymoul/?rev=84&view=rev
Author: tiran
Date: 2007-01-26 08:40:35 -0800 (Fri, 26 Jan 2007)
Log Message:
-----------
Add two other modules about process infos (could be useful but I have to test them)
Added Paths:
-----------
pymoul/trunk/src/moul/osdependent/win32/enumprocesses.py
pymoul/trunk/src/moul/osdependent/win32/processinfo.py
Added: pymoul/trunk/src/moul/osdependent/win32/enumprocesses.py
===================================================================
--- pymoul/trunk/src/moul/osdependent/win32/enumprocesses.py (rev 0)
+++ pymoul/trunk/src/moul/osdependent/win32/enumprocesses.py 2007-01-26 16:40:35 UTC (rev 84)
@@ -0,0 +1,63 @@
+"""
+Enumerates active processes as seen under windows Task Manager on Win NT/2k/XP using PSAPI.dll
+(new api for processes) and using ctypes.Use it as you please.
+
+Based on information from http://support.microsoft.com/default.aspx?scid=KB;EN-US;Q175030&ID=KB;EN-US;Q175030
+
+By Eric Koome
+email ek...@ya...
+license GPL
+"""
+#http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/305279
+#Title: getting process information on windows
+#Submitter: Eric Koome (other recipes)
+#Last Updated: 2004/09/22
+#Version no: 1.3
+#Category:
+
+from ctypes import *
+
+#PSAPI.DLL
+psapi = windll.psapi
+#Kernel32.DLL
+kernel = windll.kernel32
+
+def EnumProcesses():
+ arr = c_ulong * 256
+ lpidProcess= arr()
+ cb = sizeof(lpidProcess)
+ cbNeeded = c_ulong()
+ hModule = c_ulong()
+ count = c_ulong()
+ modname = c_buffer(30)
+ PROCESS_QUERY_INFORMATION = 0x0400
+ PROCESS_VM_READ = 0x0010
+
+ #Call Enumprocesses to get hold of process id's
+ psapi.EnumProcesses(byref(lpidProcess),
+ cb,
+ byref(cbNeeded))
+
+ #Number of processes returned
+ nReturned = cbNeeded.value/sizeof(c_ulong())
+
+ pidProcess = [i for i in lpidProcess][:nReturned]
+
+ for pid in pidProcess:
+
+ #Get handle to the process based on PID
+ hProcess = kernel.OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ,
+ False, pid)
+ if hProcess:
+ psapi.EnumProcessModules(hProcess, byref(hModule), sizeof(hModule), byref(count))
+ psapi.GetModuleBaseNameA(hProcess, hModule.value, modname, sizeof(modname))
+ print "".join([ i for i in modname if i != '\x00'])
+
+ #-- Clean up
+ for i in range(modname._length_):
+ modname[i]='\x00'
+
+ kernel.CloseHandle(hProcess)
+
+if __name__ == '__main__':
+ EnumProcesses()
\ No newline at end of file
Property changes on: pymoul/trunk/src/moul/osdependent/win32/enumprocesses.py
___________________________________________________________________
Name: svn:eol-style
+ native
Added: pymoul/trunk/src/moul/osdependent/win32/processinfo.py
===================================================================
--- pymoul/trunk/src/moul/osdependent/win32/processinfo.py (rev 0)
+++ pymoul/trunk/src/moul/osdependent/win32/processinfo.py 2007-01-26 16:40:35 UTC (rev 84)
@@ -0,0 +1,34 @@
+#http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/303339
+#Title: getting process information on windows
+#Submitter: John Nielsen (other recipes)
+#Last Updated: 2004/09/03
+#Version no: 1.0
+#Category: System
+
+import win32pdh, string, win32api
+
+def procids():
+ #each instance is a process, you can have multiple processes w/same name
+ junk, instances = win32pdh.EnumObjectItems(None,None,'process', win32pdh.PERF_DETAIL_WIZARD)
+ proc_ids=[]
+ proc_dict={}
+ for instance in instances:
+ if instance in proc_dict:
+ proc_dict[instance] = proc_dict[instance] + 1
+ else:
+ proc_dict[instance]=0
+ for instance, max_instances in proc_dict.items():
+ for inum in xrange(max_instances+1):
+ hq = win32pdh.OpenQuery() # initializes the query handle
+ path = win32pdh.MakeCounterPath( (None,'process',instance, None, inum,'ID Process') )
+ counter_handle=win32pdh.AddCounter(hq, path)
+ win32pdh.CollectQueryData(hq) #collects data for the counter
+ type, val = win32pdh.GetFormattedCounterValue(counter_handle, win32pdh.PDH_FMT_LONG)
+ proc_ids.append((instance,str(val)))
+ win32pdh.CloseQuery(hq)
+
+ proc_ids.sort()
+ return proc_ids
+
+
+print procids()
\ No newline at end of file
Property changes on: pymoul/trunk/src/moul/osdependent/win32/processinfo.py
___________________________________________________________________
Name: svn:eol-style
+ native
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <ti...@us...> - 2007-01-26 16:29:25
|
Revision: 83
http://pymoul.svn.sourceforge.net/pymoul/?rev=83&view=rev
Author: tiran
Date: 2007-01-26 08:29:18 -0800 (Fri, 26 Jan 2007)
Log Message:
-----------
added test thread
WMI is not thread safe :(
Modified Paths:
--------------
pymoul/trunk/src/moul/qt/mainwindow.py
pymoul/trunk/src/moul/qt/moulqt.py
Modified: pymoul/trunk/src/moul/qt/mainwindow.py
===================================================================
--- pymoul/trunk/src/moul/qt/mainwindow.py 2007-01-26 15:15:00 UTC (rev 82)
+++ pymoul/trunk/src/moul/qt/mainwindow.py 2007-01-26 16:29:18 UTC (rev 83)
@@ -33,6 +33,7 @@
from moul.qt.ui.mainwindow import Ui_MainWindow
from moul.qt.localization import LocalizationMixin
+from moul.osdependent import isMoulRunning
from moul.config import lookupDir
from moul.file.wdysini import AudioIni
from moul.file.wdysini import GraphicsIni
@@ -45,6 +46,17 @@
LOG = getLogger('moul.qt')
+def criticalMessageBox(self, title, text):
+ """Critical warning!
+ """
+ mb = QtGui.QMessageBox()
+ mb.setWindowIcon(QtGui.QIcon(":/resources/uru_icon_32x32.png"))
+ mb.setIcon(QtGui.QMessageBox.Critical)
+ mb.setWindowTitle(self.trUtf8(title))
+ mb.setText(self.trUtf8(text))
+ mb.setStandardButtons(QtGui.QMessageBox.Close)
+ return mb
+
class MainWindow(QtGui.QMainWindow, Ui_MainWindow, LocalizationMixin):
def __init__(self):
QtGui.QMainWindow.__init__(self)
@@ -69,7 +81,17 @@
self._systray_init()
self.tab_documents.setEnabled(False)
self._documents_init()
+
+ # run checker
+ self._moulrunning_thread = MoulRunningThread()
+ self.connect(self._moulrunning_thread, SIGNAL('moulIsRunning(bool)'),
+ self.on_moulIsRunning)
+ self._moulrunning_thread.startChecker(10.0) # check now and every 10 seconds
+ @signalLogDecorator(LOG)
+ def on_moulIsRunning(self, bool):
+ pass
+
def _notimplemented(self):
"""TODO: remove me
"""
@@ -493,11 +515,13 @@
self._servers = None
def pingServers(self, servers):
+ # TODO: thread safety!
self.servers = servers
if not self.isRunning():
self.start()
def run(self):
+ # TODO: thread safety!
self.emit(SIGNAL("started"))
# emit a list of names first
for server in self.servers:
@@ -520,3 +544,39 @@
self.emit(SIGNAL("ping(const QString&, float)"), name, ping)
self.emit(SIGNAL("done()"))
+
+class MoulRunningThread(QtCore.QThread):
+ def __init__(self, parent=None):
+ QtCore.QThread.__init__(self, parent)
+ self.mutex = QtCore.QMutex()
+ self.condition = QtCore.QWaitCondition()
+ self._timer = None
+ self._running = False
+
+ def startChecker(self, timer):
+ self._timer = long(timer * 1000)
+ if not self.isRunning():
+ self._running = True
+ self.start()
+
+ def stopChecker(self):
+ # TODO check this
+ self._running = False
+ self.condition.wakeAll()
+
+ def __del__(self):
+ self.stopChecker()
+
+ def run(self):
+ while True:
+ result = True #isMoulRunning()
+ if result:
+ self.emit(SIGNAL('moulIsRunning(bool)'), True)
+ else:
+ self.emit(SIGNAL('moulIsRunning(bool)'), False)
+
+ self.mutex.lock()
+ self.condition.wait(self.mutex, self._timer)
+ self.mutex.unlock()
+ if not self._running:
+ return
Modified: pymoul/trunk/src/moul/qt/moulqt.py
===================================================================
--- pymoul/trunk/src/moul/qt/moulqt.py 2007-01-26 15:15:00 UTC (rev 82)
+++ pymoul/trunk/src/moul/qt/moulqt.py 2007-01-26 16:29:18 UTC (rev 83)
@@ -27,36 +27,28 @@
from PyQt4 import QtGui
from moul.qt.mainwindow import MainWindow
+from moul.qt.mainwindow import criticalMessageBox
from moul.osdependent.singleapp import SimpleSingleApp
from moul.config import getPyMoulDataDir
from moul.osdependent import isMoulRunning
-def critical(self, title, text):
- """Critical warning!
- """
- mb = QtGui.QMessageBox()
- mb.setWindowIcon(QtGui.QIcon(":/resources/uru_icon_32x32.png"))
- mb.setIcon(QtGui.QMessageBox.Critical)
- mb.setWindowTitle(self.trUtf8(title))
- mb.setText(self.trUtf8(text))
- mb.setStandardButtons(QtGui.QMessageBox.Close)
- return mb
-
def main(*args):
app = QtGui.QApplication(*args)
singleapp = SimpleSingleApp('pymoulqt', path=getPyMoulDataDir())
try:
singleapp.acquire()
except OSError:
- mb = critical(app, "pyMoul QT already running",
+ mb = criticalMessageBox(app,
+ "pyMoul QT already running",
"""An instance of pyMoul QT is already running!""")
mb.exec_()
sys.exit(1)
- if isMoulRunning():
- mb = critical(app, "URU is running",
- """URU is running! Please close Uru or Uru Launcher first.""")
- mb.exec_()
- sys.exit(2)
+ #if isMoulRunning():
+ # mb = criticalMessageBox(app,
+ # "URU is running",
+ # """URU is running! Please close Uru or Uru Launcher first.""")
+ # mb.exec_()
+ # sys.exit(2)
mainWindow = MainWindow()
mainWindow.show()
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <ti...@us...> - 2007-01-26 15:15:02
|
Revision: 82
http://pymoul.svn.sourceforge.net/pymoul/?rev=82&view=rev
Author: tiran
Date: 2007-01-26 07:15:00 -0800 (Fri, 26 Jan 2007)
Log Message:
-----------
Fixed exe build
Check for isMoulRunning inside QT ui
Modified Paths:
--------------
pymoul/trunk/setup_win32.py
pymoul/trunk/src/moul/log.py
pymoul/trunk/src/moul/osdependent/__init__.py
pymoul/trunk/src/moul/qt/moulqt.py
Modified: pymoul/trunk/setup_win32.py
===================================================================
--- pymoul/trunk/setup_win32.py 2007-01-26 14:55:52 UTC (rev 81)
+++ pymoul/trunk/setup_win32.py 2007-01-26 15:15:00 UTC (rev 82)
@@ -68,11 +68,12 @@
pexe = kw['options'].setdefault('py2exe', {})
pexe['compressed'] = 100 # compress zip file
pexe['optimize'] = 0 # 0,1,2
- pexe['includes'] = ['sip', 'PyQt4', 'encodings', 'encodings.*']
+ pexe['includes'] = ['sip', 'PyQt4', 'encodings', 'encodings.*',
+ 'moul.osdependent.win32', 'moul.osdependent.win32.*']
# SSL currently not in use but imported by socket
pexe['excludes'] = ['_ssl']
# added by platform but not yet required
- pexe['excludes'].extend(('win32pipe', 'win32api', 'win32con', 'win32evtlog'))
+ #pexe['excludes'].extend(('win32pipe', 'win32api', 'win32con', 'win32evtlog'))
# added by logging.handlers.SMTPHandler but not yet required
pexe['excludes'].append('smtplib')
# UPX
Modified: pymoul/trunk/src/moul/log.py
===================================================================
--- pymoul/trunk/src/moul/log.py 2007-01-26 14:55:52 UTC (rev 81)
+++ pymoul/trunk/src/moul/log.py 2007-01-26 15:15:00 UTC (rev 82)
@@ -113,12 +113,12 @@
#_systemInfo()
else:
_installMemoryHdlr()
- # Redirect stdout and stderr to logger when running as frozen app
- sys.stdout = LoggingStdout(getLogger('stdout').info)
- sys.stderr = LoggingStdout(getLogger('stderr').error)
_systemInfo()
_installFileHdlr()
_removeMemoryHdlr()
+ # Redirect stdout and stderr to logger when running as frozen app
+ #sys.stdout = LoggingStdout(getLogger('stdout').info)
+ #sys.stderr = LoggingStdout(getLogger('stderr').error)
__LOG_SIGNALS__ = not __FROZEN__
def signalLogDecorator(__logger__):
Modified: pymoul/trunk/src/moul/osdependent/__init__.py
===================================================================
--- pymoul/trunk/src/moul/osdependent/__init__.py 2007-01-26 14:55:52 UTC (rev 81)
+++ pymoul/trunk/src/moul/osdependent/__init__.py 2007-01-26 15:15:00 UTC (rev 82)
@@ -35,7 +35,10 @@
import os
import sys
+from moul.log import getLogger
+LOG = getLogger('moul.osdependent')
+
# a program under py2exe is sys.frozen
__FROZEN__ = bool(getattr(sys, 'frozen', False))
# OS stuff
Modified: pymoul/trunk/src/moul/qt/moulqt.py
===================================================================
--- pymoul/trunk/src/moul/qt/moulqt.py 2007-01-26 14:55:52 UTC (rev 81)
+++ pymoul/trunk/src/moul/qt/moulqt.py 2007-01-26 15:15:00 UTC (rev 82)
@@ -29,21 +29,34 @@
from moul.qt.mainwindow import MainWindow
from moul.osdependent.singleapp import SimpleSingleApp
from moul.config import getPyMoulDataDir
+from moul.osdependent import isMoulRunning
+def critical(self, title, text):
+ """Critical warning!
+ """
+ mb = QtGui.QMessageBox()
+ mb.setWindowIcon(QtGui.QIcon(":/resources/uru_icon_32x32.png"))
+ mb.setIcon(QtGui.QMessageBox.Critical)
+ mb.setWindowTitle(self.trUtf8(title))
+ mb.setText(self.trUtf8(text))
+ mb.setStandardButtons(QtGui.QMessageBox.Close)
+ return mb
+
def main(*args):
app = QtGui.QApplication(*args)
singleapp = SimpleSingleApp('pymoulqt', path=getPyMoulDataDir())
try:
singleapp.acquire()
except OSError:
- mb = QtGui.QMessageBox()
- mb.setWindowIcon(QtGui.QIcon(":/resources/uru_icon_32x32.png"))
- mb.setIcon(QtGui.QMessageBox.Critical)
- mb.setWindowTitle(app.trUtf8("Already running"))
- mb.setText(app.trUtf8("""An instance of pyMoul QT is already running!"""))
- mb.setStandardButtons(QtGui.QMessageBox.Close)
+ mb = critical(app, "pyMoul QT already running",
+ """An instance of pyMoul QT is already running!""")
mb.exec_()
sys.exit(1)
+ if isMoulRunning():
+ mb = critical(app, "URU is running",
+ """URU is running! Please close Uru or Uru Launcher first.""")
+ mb.exec_()
+ sys.exit(2)
mainWindow = MainWindow()
mainWindow.show()
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <ti...@us...> - 2007-01-26 14:55:56
|
Revision: 81
http://pymoul.svn.sourceforge.net/pymoul/?rev=81&view=rev
Author: tiran
Date: 2007-01-26 06:55:52 -0800 (Fri, 26 Jan 2007)
Log Message:
-----------
Added isMoulRunning stuff
Enhanced startMoul
Added some (disabled) tests for start and is running
Modified Paths:
--------------
pymoul/trunk/src/moul/config/__init__.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
Modified: pymoul/trunk/src/moul/config/__init__.py
===================================================================
--- pymoul/trunk/src/moul/config/__init__.py 2007-01-26 14:17:50 UTC (rev 80)
+++ pymoul/trunk/src/moul/config/__init__.py 2007-01-26 14:55:52 UTC (rev 81)
@@ -16,6 +16,30 @@
# Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
"""Configuration package
+
+>>> from moul.osdependent import startMoul
+>>> from moul.osdependent import isMoulRunning
+>>> installDir = lookupDir('install')
+>>> from time import sleep
+
+Start MOUL
+#>>> popen = startMoul(installDir)
+
+Wait a bit before testing the rest
+#>>> sleep(0.2)
+#>>> bool(popen.pid)
+True
+#>>> popen.poll()
+#>>> popen.returncode is None
+True
+
+Check the running tester
+#>>> isMoulRunning()
+u'urulauncher.exe'
+
+#>>> popen.wait()
+#>>> popen.returncode
+#0
"""
import os
Modified: pymoul/trunk/src/moul/osdependent/__init__.py
===================================================================
--- pymoul/trunk/src/moul/osdependent/__init__.py 2007-01-26 14:17:50 UTC (rev 80)
+++ pymoul/trunk/src/moul/osdependent/__init__.py 2007-01-26 14:55:52 UTC (rev 81)
@@ -53,7 +53,7 @@
# names to import: from moul.osdependent.ID import NAME (as NAME)
NAMES = ('getMoulUserDataDir',
('getPyMoulDataDir', '_getPyMoulDataDir'), # as
- '_startMOUL', 'EXEC_NAME',
+ 'startMoul', 'isMoulRunning',
'getCurrentPids', 'getCurrentPidNames',
)
Modified: pymoul/trunk/src/moul/osdependent/darwin/__init__.py
===================================================================
--- pymoul/trunk/src/moul/osdependent/darwin/__init__.py 2007-01-26 14:17:50 UTC (rev 80)
+++ pymoul/trunk/src/moul/osdependent/darwin/__init__.py 2007-01-26 14:55:52 UTC (rev 81)
@@ -22,9 +22,12 @@
__revision__ = "$Revision$"
import os
-from moul.log import LOG
-LOG.warning('Darwin/Mac support is not tested')
+from subprocess import Popen
+from moul.log import getLogger
+LOG = getLogger('moul.darwin')
+LOG.critical('Darwin/Mac support is not tested')
+
MOUL_DIR = "Uru Live"
EXEC_NAME = "UruLauncher"
HOME = os.environ['HOME']
@@ -43,12 +46,12 @@
inidir= os.path.join(HOME, '.pymoul')
return inidir
-def _startMOUL(installdir, *args):
- """Start MOUL
+def startMoul(installdir, *args, **kwargs):
+ """Start MOUL - returns a Popen instance
+
+ args are applied to the program while kwargs are applied to
+ subprocess.Popen()
"""
- # P_DETACH is similar to P_NOWAIT, but the new process is detached from
- # the console of the calling process.
- mode = os.P_DETACH
path = os.path.join(installdir, EXEC_NAME)
- args = (EXEC_NAME,) + args
- return os.spawnv(mode, path, args)
+ args = ' '.join(args)
+ return Popen("%s %s" % (path, args), cwd=installdir, **kwargs)
Modified: pymoul/trunk/src/moul/osdependent/linux/__init__.py
===================================================================
--- pymoul/trunk/src/moul/osdependent/linux/__init__.py 2007-01-26 14:17:50 UTC (rev 80)
+++ pymoul/trunk/src/moul/osdependent/linux/__init__.py 2007-01-26 14:55:52 UTC (rev 81)
@@ -22,13 +22,17 @@
__revision__ = "$Revision$"
import os
-from moul.log import LOG
-LOG.warning('Linux support is not tested')
+from subprocess import Popen
+from moul.log import getLogger
+LOG = getLogger('moul.linux')
+LOG.critical('Darwin/Mac support is not tested')
+
MOUL_DIR = "Uru Live"
INI_FILE = ('pyMoul', 'pymoul.ini')
EXEC_NAME = "UruLauncher"
HOME = os.environ['HOME']
+PROCESSES = ('urulauncher', 'uruexplorer')
def getMoulUserDataDir():
"""Get path of MOUL data directory
@@ -44,19 +48,26 @@
inidir= os.path.join(HOME, '.pymoul')
return inidir
-def _startMOUL(installdir, *args):
- """Start MOUL
+def startMoul(installdir, *args, **kwargs):
+ """Start MOUL - returns a Popen instance
+
+ args are applied to the program while kwargs are applied to
+ subprocess.Popen()
"""
- # P_DETACH is similar to P_NOWAIT, but the new process is detached from
- # the console of the calling process.
- mode = os.P_DETACH
path = os.path.join(installdir, EXEC_NAME)
- args = (EXEC_NAME,) + args
- return os.spawnv(mode, path, args)
+ args = ' '.join(args)
+ return Popen("%s %s" % (path, args), cwd=installdir, **kwargs)
+def isMoulRunning():
+ """Test if MOUL or the launcher is running
+ """
+ for pid, name in getCurrentPidNames().items():
+ if name.lower() in PROCESSES:
+ return name.lower()
+ return False
+
# process info
# based on http://gelb.bcom.at/trac/misc/browser/processinfo
-
def getCurrentPids():
"""Returns current process ids
"""
Modified: pymoul/trunk/src/moul/osdependent/win32/__init__.py
===================================================================
--- pymoul/trunk/src/moul/osdependent/win32/__init__.py 2007-01-26 14:17:50 UTC (rev 80)
+++ pymoul/trunk/src/moul/osdependent/win32/__init__.py 2007-01-26 14:55:52 UTC (rev 81)
@@ -22,18 +22,25 @@
__revision__ = "$Revision$"
import os
+from subprocess import Popen
+
from moul.osdependent.win32.miniwinshell import my_documents as getMyDocuments
from moul.osdependent.win32.miniwinshell import application_data as getAppdata
#from moul.osdependent.win32.winpath import get_homedir as getMyDocuments
#from moul.osdependent.win32.winpath import get_appdata as getAppdata
from moul.osdependent.win32 import wmi
+from moul.log import getLogger
+LOG = getLogger('moul.win')
+
MOUL_DIR = "Uru Live"
-EXEC_NAME = "UruLauncher.exe"
+EXEC_NAME = "UruLauncher.exe"
+# lower case
+PROCESSES = ("urulauncher.exe", "uruexplorer.exe")
-mycomputer = None
-mydocs = getMyDocuments()
-myappdata = getAppdata()
+MYCOMPUTER = None # wmi instance
+MYDOCS = getMyDocuments()
+MYAPPDATA = getAppdata()
def getMoulUserDataDir():
"""Get path of MOUL data directory
@@ -41,41 +48,48 @@
The MOUL data directory contains log files, chatlogs, KI images and many
more things.
"""
- moul_data = os.path.join(mydocs, MOUL_DIR)
+ moul_data = os.path.join(MYDOCS, MOUL_DIR)
return moul_data
def getPyMoulDataDir():
"""Get path to the pyMoul ini file
"""
- inidir = os.path.join(myappdata , 'pyMoul')
+ inidir = os.path.join(MYAPPDATA , 'pyMoul')
return inidir
-def _startMOUL(installdir, *args):
- """Start MOUL
+def startMoul(installdir, *args, **kwargs):
+ """Start MOUL - returns a Popen instance
+
+ args are applied to the program while kwargs are applied to
+ subprocess.Popen()
"""
- # TODO: use subprocess module
- # P_DETACH is similar to P_NOWAIT, but the new process is detached from
- # the console of the calling process.
- mode = os.P_DETACH
path = os.path.join(installdir, EXEC_NAME)
- args = (EXEC_NAME,) + args
- return os.spawnv(mode, path, args)
+ args = ' '.join(args)
+ return Popen("%s %s" % (path, args), cwd=installdir, **kwargs)
+def isMoulRunning():
+ """Test if MOUL or the launcher is running
+ """
+ for pid, name in getCurrentPidNames().items():
+ if name.lower() in PROCESSES:
+ return name.lower()
+ return False
+
def getCurrentPids():
"""Returns mapping pid -> name
"""
- global mycomputer
- if mycomputer is None:
+ global MYCOMPUTER
+ if MYCOMPUTER is None:
# XXX: extremely slow, also see getCurrentPidNames
- mycomputer = wmi.WMI()
- return [process.ProcessId for process in mycomputer.Win32_Process()]
+ MYCOMPUTER = wmi.WMI()
+ return [process.ProcessId for process in MYCOMPUTER.Win32_Process()]
def getCurrentPidNames():
"""Returns mapping pid -> name
"""
- global mycomputer
- if mycomputer is None:
- mycomputer = wmi.WMI()
+ global MYCOMPUTER
+ if MYCOMPUTER is None:
+ MYCOMPUTER = wmi.WMI()
return dict([(process.ProcessId, process.Name)
- for process in mycomputer.Win32_Process()
+ for process in MYCOMPUTER.Win32_Process()
])
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <ti...@us...> - 2007-01-26 14:17:52
|
Revision: 80
http://pymoul.svn.sourceforge.net/pymoul/?rev=80&view=rev
Author: tiran
Date: 2007-01-26 06:17:50 -0800 (Fri, 26 Jan 2007)
Log Message:
-----------
More cleanups
Use WMI (f.... slow) to get process informations under Linux. Memo to me: put it inside a thread
Moved os specific stuff around
Modified Paths:
--------------
pymoul/trunk/src/moul/config/__init__.py
pymoul/trunk/src/moul/log.py
pymoul/trunk/src/moul/osdependent/__init__.py
pymoul/trunk/src/moul/osdependent/linux/__init__.py
pymoul/trunk/src/moul/osdependent/processinfo.py
pymoul/trunk/src/moul/osdependent/win32/__init__.py
pymoul/trunk/src/moul/qt/ui/mainwindow.py
Added Paths:
-----------
pymoul/trunk/src/moul/osdependent/tests/test_osdependent.py
pymoul/trunk/src/moul/osdependent/win32/wmi.py
Modified: pymoul/trunk/src/moul/config/__init__.py
===================================================================
--- pymoul/trunk/src/moul/config/__init__.py 2007-01-26 02:16:36 UTC (rev 79)
+++ pymoul/trunk/src/moul/config/__init__.py 2007-01-26 14:17:50 UTC (rev 80)
@@ -18,70 +18,13 @@
"""Configuration package
"""
import os
-import sys
-from logging import getLogger
-LOG = getLogger('pyMoul')
+from moul.osdependent import getMoulUserDataDir
+from moul.osdependent import getPyMoulDataDir
-# a program under py2exe is sys.frozen
-__FROZEN__ = bool(getattr(sys, 'frozen', False))
-# OS stuff
-__WIN32__ = sys.platform.startswith('win32') # win64, cygwin?
-__LINUX__ = sys.platform.startswith('linux2')
-__MACOSX__ = sys.platform.startswith('darwin')
-__UNIX__ = __LINUX__ or __MACOSX__
-
-LOG.debug("sys.frozen status: %s" % __FROZEN__)
-LOG.debug("OS detected: win32: %s, Linux: %s, Mac: %s, Un*x: %s" %
- (__WIN32__, __LINUX__, __MACOSX__, __UNIX__))
-
_marker=object()
-# XXX: what about cygwin, bsd and others?
-if __WIN32__:
- from moul.osdependent.win32 import (
- getMoulUserDataDir,
- getPyMoulDataDir as _getPyMoulDataDir,
- _startMOUL,
- EXEC_NAME
- )
-elif __LINUX__:
- from moul.osdependent.linux import (
- getMoulUserDataDir,
- getPyMoulDataDir as _getPyMoulDataDir,
- _startMOUL,
- EXEC_NAME
- )
-elif __MACOSX__:
- from moul.osdependent.darwin import (
- getMoulUserDataDir,
- getPyMoulDataDir as _getPyMoulDataDir,
- _startMOUL,
- EXEC_NAME
- )
-else:
- raise RuntimeError('platform %s not supported' % sys.platform)
-def getPyMoulDataDir(check=False):
- """Get pyMoul data directory
-
- The directory contains log files, ini files and other local stuff
- """
- datadir = _getPyMoulDataDir()
- if check:
- if os.path.abspath(datadir) != datadir:
- raise ValueError("Datadir is not absolute %s" % datadir)
- if not os.path.isdir(datadir):
- parent = os.path.abspath(os.path.join(datadir, os.pardir))
- if not os.path.isdir(parent):
- raise ValueError("Datadir's parent dir does not exist: %s"
- % par)
- else:
- LOG.debug("Creating pyMoul data dir %s" % datadir)
- os.mkdir(datadir, 0750)
- LOG.debug("Using pyMoul data dir %s" % datadir)
- return datadir
-
-## configuration
+# configuration
class Configuration(dict):
def __new__(cls, *args, **kwargs):
self = dict.__new__(cls, *args, **kwargs)
Modified: pymoul/trunk/src/moul/log.py
===================================================================
--- pymoul/trunk/src/moul/log.py 2007-01-26 02:16:36 UTC (rev 79)
+++ pymoul/trunk/src/moul/log.py 2007-01-26 14:17:50 UTC (rev 80)
@@ -33,9 +33,7 @@
getLogger = logging.getLogger
-# copied from moul.config to prevent circular imports
__FROZEN__ = bool(getattr(sys, 'frozen', False))
-__LOG_SIGNALS__ = not __FROZEN__
format = Formatter('%(asctime)s %(name)-8s %(levelname)-7s %(message)s',
#'%a, %d %b %Y %H:%M:%S'
@@ -92,6 +90,7 @@
fhdlr.doRollover()
def _systemInfo():
+ from moul.osdependent import __INFO__
LOG.debug("pyMoul version: %s" % moul_version)
LOG.debug("Python: %s" % repr(sys.version_info))
LOG.debug("Python: %s" % sys.version.replace('\n', ' '))
@@ -99,6 +98,9 @@
LOG.debug("system %r, node %r, release %r, version %r, machine %r, processor %r"
% platform.uname())
LOG.debug("platform name: %s" % platform.platform(True))
+ LOG.debug("sys.frozen status: %s" % __FROZEN__)
+ LOG.debug("OS detected: win32: %r, cygwin: %r, Linux: %r, Mac: %r, BSD: %r, "
+ "posix/Un*x: %r, NT: %r" % __INFO__)
# no setup the logging stuff!
@@ -108,6 +110,7 @@
shdlr = logging.StreamHandler(sys.stderr)
shdlr.setFormatter(format)
root.addHandler(shdlr)
+ #_systemInfo()
else:
_installMemoryHdlr()
# Redirect stdout and stderr to logger when running as frozen app
@@ -117,6 +120,7 @@
_installFileHdlr()
_removeMemoryHdlr()
+__LOG_SIGNALS__ = not __FROZEN__
def signalLogDecorator(__logger__):
"""Decorator to log signals
Modified: pymoul/trunk/src/moul/osdependent/__init__.py
===================================================================
--- pymoul/trunk/src/moul/osdependent/__init__.py 2007-01-26 02:16:36 UTC (rev 79)
+++ pymoul/trunk/src/moul/osdependent/__init__.py 2007-01-26 14:17:50 UTC (rev 80)
@@ -15,8 +15,118 @@
# with this program; if not, write to the Free Software Foundation, Inc., 59
# Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
+"""OS dependent code for linux, mac and win32
+
+>>> pids = getCurrentPids()
+>>> len(pids) > 1
+True
+
+>>> pids = getCurrentPidNames()
+>>> found = False
+>>> for pid, name in pids.items():
+... if name.lower().startswith('python'):
+... found = True
+>>> found
+True
"""
-"""
__author__ = "Christian Heimes"
__version__ = "$Id$"
__revision__ = "$Revision$"
+
+import os
+import sys
+
+# a program under py2exe is sys.frozen
+__FROZEN__ = bool(getattr(sys, 'frozen', False))
+# OS stuff
+_plat = sys.platform.startswith
+__WIN32__ = _plat('win32') # win64, cygwin?
+__CYGWIN__ = _plat('cygwin')
+__LINUX__ = _plat('linux2')
+__MACOSX__ = _plat('darwin')
+__BSD__ = _plat('freebsd') or _plat('netbsd') or _plat('openbsd')
+__POSIX__ = os.name.lower() == 'posix'
+__NT__ = os.name.lower() == 'nt'
+__INFO__ = (__WIN32__, __CYGWIN__, __LINUX__, __MACOSX__, __BSD__,
+ __POSIX__, __NT__)
+
+# names to import: from moul.osdependent.ID import NAME (as NAME)
+NAMES = ('getMoulUserDataDir',
+ ('getPyMoulDataDir', '_getPyMoulDataDir'), # as
+ '_startMOUL', 'EXEC_NAME',
+ 'getCurrentPids', 'getCurrentPidNames',
+ )
+
+_marker = object()
+
+def _importHelper(modname, names=None, target=None):
+ """Import a list of variables from a module
+
+ >>> mod = _importHelper('moul.osdependent')
+ >>> mod == _thismodule or mod
+ True
+ >>> vars = _importHelper('moul.osdependent', ('_marker', ))
+ >>> vars[0] is _marker
+ True
+ >>> class Target(object):
+ ... pass
+ >>> target = Target()
+ >>> vars = _importHelper('moul.osdependent', ('_marker', ), target=target)
+ >>> target._marker is _marker
+ True
+ >>> vars[0] is _marker
+ True
+
+ >>> vars = _importHelper('moul.osdependent', (('_marker', 'another'), ),
+ ... target=target)
+ >>> target.another is _marker
+ True
+ >>> vars[0] is _marker
+ True
+ """
+ mod = __import__(modname, globals(), locals(), [''])
+ if names is None:
+ return mod
+ else:
+ vars = []
+ for name in names:
+ if isinstance(name, (tuple, list)):
+ name, nameas = name
+ else:
+ nameas = name
+ var = getattr(mod, name)
+ vars.append(var)
+ if target is not None:
+ setattr(target, nameas, var)
+ return vars
+
+# XXX: what about cygwin, bsd and others?
+_thismodule = sys.modules[__name__]
+if __WIN32__:
+ _importHelper('moul.osdependent.win32', NAMES, target=_thismodule)
+elif __LINUX__:
+ _importHelper('moul.osdependent.linux', NAMES, target=_thismodule)
+elif __MACOSX__:
+ _importHelper('moul.osdependent.darwin', NAMES, target=_thismodule)
+else:
+ raise RuntimeError('platform %s not supported' % sys.platform)
+
+def getPyMoulDataDir(check=False):
+ """Get pyMoul data directory
+
+ The directory contains log files, ini files and other local stuff
+ """
+ datadir = _getPyMoulDataDir()
+ if check:
+ if os.path.abspath(datadir) != datadir:
+ raise ValueError("Datadir is not absolute %s" % datadir)
+ if not os.path.isdir(datadir):
+ parent = os.path.abspath(os.path.join(datadir, os.pardir))
+ if not os.path.isdir(parent):
+ raise ValueError("Datadir's parent dir does not exist: %s"
+ % par)
+ else:
+ LOG.debug("Creating pyMoul data dir %s" % datadir)
+ os.mkdir(datadir, 0750)
+ LOG.debug("Using pyMoul data dir %s" % datadir)
+ return datadir
Modified: pymoul/trunk/src/moul/osdependent/linux/__init__.py
===================================================================
--- pymoul/trunk/src/moul/osdependent/linux/__init__.py 2007-01-26 02:16:36 UTC (rev 79)
+++ pymoul/trunk/src/moul/osdependent/linux/__init__.py 2007-01-26 14:17:50 UTC (rev 80)
@@ -53,3 +53,52 @@
path = os.path.join(installdir, EXEC_NAME)
args = (EXEC_NAME,) + args
return os.spawnv(mode, path, args)
+
+# process info
+# based on http://gelb.bcom.at/trac/misc/browser/processinfo
+
+def getCurrentPids():
+ """Returns current process ids
+ """
+ pids = []
+ for fname in os.listdir("/proc"):
+ if os.path.isdir(os.path.join("/proc", fname)):
+ try:
+ pids.append(int(fname))
+ except ValueError:
+ continue
+ return pids
+
+def getCurrentPidDetails():
+ """Returns mapping pid -> detailed informations
+ """
+ mapping = {}
+ for pid in getCurrentPids():
+ try:
+ try:
+ # read entiry file to avoid race condition bugs
+ fd = open('/proc/%i/status' % pid, 'rb')
+ status = fd.read().split('\n')
+ finally:
+ if fd:
+ fd.close()
+ except IoError:
+ continue
+ details = {}
+ for line in status:
+ try:
+ key, value = line.split(':\t')
+ except ValueError:
+ continue
+ details[key.lower()] = value.strip()
+ mapping[pid] = details
+
+ return mapping
+
+def getCurrentPidNames():
+ """Returns mapping pid -> name
+ """
+ mapping = {}
+ for pid, details in getCurrentPidDetails().items():
+ mapping[pid] = details.get('name', None)
+ return mapping
Modified: pymoul/trunk/src/moul/osdependent/processinfo.py
===================================================================
--- pymoul/trunk/src/moul/osdependent/processinfo.py 2007-01-26 02:16:36 UTC (rev 79)
+++ pymoul/trunk/src/moul/osdependent/processinfo.py 2007-01-26 14:17:50 UTC (rev 80)
@@ -1,219 +1,219 @@
-#!/usr/bin/env python
-# -*- coding: iso-8859-1 -*-
-"""Process info
-
-Based on http://gelb.bcom.at/trac/misc/browser/processinfo
-
-Modified and optimized by Christian Heimes
-"""
-
-import sys
-import os
-
-__all__ = ['PLATFORM', 'UnsupportedOsError', 'getCurrentPids',
- 'getCurrentPidNames', 'getCurrentPidDetails']
-
-class UnsupportedOsError(NotImplementedError):
- pass
-
-PLATFORM = None
-
-_plat = sys.platform.startswith
-if _plat('win'):
- PLATFORM = 'win'
- win32process = None
- ctypes = None
- import csv
- try:
- import win32process
- except ImportError:
- try:
- import ctypes
- except ImportError:
- pass
-elif _plat('linux2') or _plat('cygwin'):
- PLATFORM = 'linux' # Linux or Cygwin
-elif _plat('darwin'):
- # XXX: unsupported
- PLATFORM = 'mac' # Mac OS X
-elif _plat('freebsd') or _plat('netbsd') or _plat('openbsd'):
- # XXX: unsupported
- PLATFORM = 'bsd' # *BSD
-else:
- PLATFORM = 'unknown'
- raise UnsupportedOsError(sys.platform)
-
-# ****************************************************************************
-# Linux / cygwin implementation
-
-def _getCurrentPids_linux():
- """
- Returns current process-id's.
-
- :return: list with process-id's.
- """
- pids = []
- for fname in os.listdir("/proc"):
- if os.path.isdir(os.path.join("/proc", fname)):
- try:
- pids.append(int(fname))
- except ValueError:
- continue
- return pids
-
-def _getCurrentPidDetails_linux():
- """Returns mapping pid -> detailed informations
- """
- mapping = {}
- for pid in getCurrentPids():
- try:
- try:
- # read entiry file to avoid race condition bugs
- fd = open('/proc/%i/status' % pid, 'rb')
- status = fd.read().split('\n')
- finally:
- if fd:
- fd.close()
- except IoError:
- continue
- details = {}
- for line in status:
- try:
- key, value = line.split(':\t')
- except ValueError:
- continue
- details[key.lower()] = value.strip()
- mapping[pid] = details
-
- return mapping
-
-# ****************************************************************************
-# Windows / win32 implementaton
-
-def _getCurrentPids_win():
- """
- Returns current process-id's.
-
- :return: List with process-id's.
- """
- if win32process is not None:
- return list(win32process.EnumProcesses())
- elif ctypes is not None:
- # ctypes is installed --> try psapi.dll
- psapi = ct.windll.psapi
- arr = ct.c_long * 1024
- process_ids = arr()
- cb = ct.sizeof(process_ids)
- bytes_returned = ct.c_ulong()
- psapi.EnumProcesses(ct.byref(process_ids), cb, ct.byref(bytes_returned))
- return sorted(list(set(process_ids)))
- else:
- csvlines = []
- current_pids = []
- for line in os.popen("tasklist.exe /fo csv /nh"):
- line = line.strip()
- if line:
- csvlines.append(line)
- for line in csv.reader(csvlines):
- current_pids.append(int(line[1]))
- if not csvlines:
- raise NotImplementedError("tasklist.exe not found (>WinXP)")
- return current_pids
-
-
-def _getCurrentPidDetails_win():
- """
- Returns processinfos. (pid, name and size_kb)
-
- On Windows-Systems, it uses ``tasklist.exe`` or WMI to list the processes.
- On other platforms, it reads the "/proc"-directory.
-
- :return: Dictionary with PID's as keys and the infos as values in an
- inner dictionary. (It is possible, that "size_kb" doesn't exist.):
- {
- 123: {"name": "bash", "pid": 123},
- 234: {"name": "mc", "pid": 234, "size_kb": 1000},
- }
- """
-
- retdict = {}
-
- # tasklist.exe runs on Windows XP and higher. (To parse the ouput of
- # tasklist.exe is faster than WMI.)
- import csv
- csvlines = []
- for line in os.popen("tasklist.exe /fo csv /nh"):
- line = line.strip()
- if line:
- csvlines.append(line)
- for line in csv.reader(csvlines):
- pid = int(line[1])
- details = {
- "name": line[0].decode("cp850"), # to unicode
- "pid": pid,
- }
- value = "".join(
- char for char in line[4]
- if char.isdigit()
- )
- details["size_kb"] = int(value)
- retdict[pid] = details
- if not csvlines:
- try:
- from win32com.client import GetObject
- # pywin32 is installed --> use WMI
- wmi = GetObject('winmgmts:')
- processes = wmi.InstancesOf('Win32_Process')
- for process in processes:
- pid = int(process.Properties_("ProcessId").value)
- details = {
- "name": process.Properties_("Name").value,
- "pid": pid,
- "size_kb": int(process.Properties_("WorkingSetSize").value) / 1000
- }
- retdict[pid] = details
- except ImportError:
- raise NotImplementedError("No tasklist.exe and no WMI.")
- return retdict
-
-# ****************************************************************************
-# general
-
-def unsupported():
- """Platform not supported
- """
- raise UnsupportedOsError(PLATFORM)
-
-def getCurrentPidNames():
- """Returns mapping pid -> name
- """
- mapping = {}
- for pid, details in getCurrentPidDetails().items():
- mapping[pid] = details.get('name', None)
- return mapping
-
-def _initialize():
- mod = sys.modules[__name__]
- for name in ('getCurrentPids','getCurrentPidDetails'):
- func = getattr(mod, "_%s_%s" % (name, PLATFORM), unsupported)
- #func.__name__ = name
- setattr(mod, name, func)
-_initialize()
-
-def main():
- """Testing"""
-
- from pprint import pformat
- # Current PIDs
- current_pids = getCurrentPids()
- print "Current PIDs: %s" % pformat(current_pids)
- print
- print "Current PID Count: %s" % len(current_pids)
- print
-
- print "Current PIDs with names: %s" % pformat(getCurrentPidNames())
- print
-
-if __name__ == "__main__":
- main()
-
+#!/usr/bin/env python
+# -*- coding: iso-8859-1 -*-
+"""Process info
+
+Based on http://gelb.bcom.at/trac/misc/browser/processinfo
+
+Modified and optimized by Christian Heimes
+"""
+
+import sys
+import os
+
+__all__ = ['PLATFORM', 'UnsupportedOsError', 'getCurrentPids',
+ 'getCurrentPidNames', 'getCurrentPidDetails']
+
+class UnsupportedOsError(NotImplementedError):
+ pass
+
+PLATFORM = None
+
+_plat = sys.platform.startswith
+if _plat('win'):
+ PLATFORM = 'win'
+ win32process = None
+ ctypes = None
+ import csv
+ try:
+ import win32process
+ except ImportError:
+ try:
+ import ctypes
+ except ImportError:
+ pass
+elif _plat('linux2') or _plat('cygwin'):
+ PLATFORM = 'linux' # Linux or Cygwin
+elif _plat('darwin'):
+ # XXX: unsupported
+ PLATFORM = 'mac' # Mac OS X
+elif _plat('freebsd') or _plat('netbsd') or _plat('openbsd'):
+ # XXX: unsupported
+ PLATFORM = 'bsd' # *BSD
+else:
+ PLATFORM = 'unknown'
+ raise UnsupportedOsError(sys.platform)
+
+# ****************************************************************************
+# Linux / cygwin implementation
+
+def _getCurrentPids_linux():
+ """
+ Returns current process-id's.
+
+ :return: list with process-id's.
+ """
+ pids = []
+ for fname in os.listdir("/proc"):
+ if os.path.isdir(os.path.join("/proc", fname)):
+ try:
+ pids.append(int(fname))
+ except ValueError:
+ continue
+ return pids
+
+def _getCurrentPidDetails_linux():
+ """Returns mapping pid -> detailed informations
+ """
+ mapping = {}
+ for pid in getCurrentPids():
+ try:
+ try:
+ # read entiry file to avoid race condition bugs
+ fd = open('/proc/%i/status' % pid, 'rb')
+ status = fd.read().split('\n')
+ finally:
+ if fd:
+ fd.close()
+ except IoError:
+ continue
+ details = {}
+ for line in status:
+ try:
+ key, value = line.split(':\t')
+ except ValueError:
+ continue
+ details[key.lower()] = value.strip()
+ mapping[pid] = details
+
+ return mapping
+
+def _getCurrentPidNames_linux():
+ """Returns mapping pid -> name
+ """
+ mapping = {}
+ for pid, details in getCurrentPidDetails().items():
+ mapping[pid] = details.get('name', None)
+ return mapping
+
+
+# ****************************************************************************
+# Windows / win32 implementaton
+
+def _getCurrentPids_win():
+ """
+ Returns current process-id's.
+
+ :return: List with process-id's.
+ """
+ if win32process is not None:
+ return list(win32process.EnumProcesses())
+ elif ctypes is not None:
+ # ctypes is installed --> try psapi.dll
+ psapi = ct.windll.psapi
+ arr = ct.c_long * 1024
+ process_ids = arr()
+ cb = ct.sizeof(process_ids)
+ bytes_returned = ct.c_ulong()
+ psapi.EnumProcesses(ct.byref(process_ids), cb, ct.byref(bytes_returned))
+ return sorted(list(set(process_ids)))
+ else:
+ csvlines = []
+ current_pids = []
+ for line in os.popen("tasklist.exe /fo csv /nh"):
+ line = line.strip()
+ if line:
+ csvlines.append(line)
+ for line in csv.reader(csvlines):
+ current_pids.append(int(line[1]))
+ if not csvlines:
+ raise NotImplementedError("tasklist.exe not found (>WinXP)")
+ return current_pids
+
+def _getCurrentPidNames_win():
+ """Returns mapping pid -> name
+ """
+ mapping = {}
+ for pid, details in getCurrentPidDetails().items():
+ mapping[pid] = details.get('name', None)
+ return mapping
+
+def _getCurrentPidDetails_win():
+ """
+ Returns processinfos. (pid, name and size_kb)
+ """
+ result = {}
+
+ # tasklist.exe runs on Windows XP and higher. (To parse the ouput of
+ # tasklist.exe is faster than WMI.)
+ csvlines = []
+ for line in os.popen("tasklist.exe /fo csv /nh"):
+ line = line.strip()
+ if line:
+ csvlines.append(line)
+ for line in csv.reader(csvlines):
+ pid = int(line[1])
+ details = {
+ "name": line[0].decode("cp850"), # to unicode
+ "pid": pid,
+ }
+ value = "".join(
+ char for char in line[4]
+ if char.isdigit()
+ )
+ details["size_kb"] = int(value)
+ retdict[pid] = details
+ if not csvlines:
+ try:
+ from win32com.client import GetObject
+ # pywin32 is installed --> use WMI
+ wmi = GetObject('winmgmts:')
+ processes = wmi.InstancesOf('Win32_Process')
+ for process in processes:
+ pid = int(process.Properties_("ProcessId").value)
+ details = {
+ "name": process.Properties_("Name").value,
+ "pid": pid,
+ "size_kb": int(process.Properties_("WorkingSetSize").value) / 1000
+ }
+ retdict[pid] = details
+ except ImportError:
+ raise NotImplementedError("No tasklist.exe and no WMI.")
+ return retdict
+
+# ****************************************************************************
+# general
+
+def unsupported():
+ """Platform not supported
+ """
+ raise UnsupportedOsError(PLATFORM)
+unsupported.__unsupported__ = True
+
+def _initialize():
+ mod = sys.modules[__name__]
+ for name in ('getCurrentPids','getCurrentPidDetails', 'getCurrentPidNames'):
+ func = getattr(mod, "_%s_%s" % (name, PLATFORM), None)
+ if func is None:
+ func = unsupported
+ else:
+ func.__name__ = name
+ setattr(mod, name, func)
+_initialize()
+
+def main():
+ """Testing"""
+
+ from pprint import pformat
+ # Current PIDs
+ current_pids = getCurrentPids()
+ print "Current PIDs: %s" % pformat(current_pids)
+ print
+ print "Current PID Count: %s" % len(current_pids)
+ print
+
+ print "Current PIDs with names: %s" % pformat(getCurrentPidNames())
+ print
+
+if __name__ == "__main__":
+ main()
+
Added: pymoul/trunk/src/moul/osdependent/tests/test_osdependent.py
===================================================================
--- pymoul/trunk/src/moul/osdependent/tests/test_osdependent.py (rev 0)
+++ pymoul/trunk/src/moul/osdependent/tests/test_osdependent.py 2007-01-26 14:17:50 UTC (rev 80)
@@ -0,0 +1,36 @@
+# 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
+#
+"""moul.osdependent.singleapp
+"""
+__author__ = "Christian Heimes"
+__version__ = "$Id$"
+__revision__ = "$Revision$"
+
+import unittest
+from doctest import DocTestSuite
+
+import moul.osdependent
+
+def test_suite():
+ return unittest.TestSuite((
+ DocTestSuite('moul.osdependent'),
+ ))
+
+if __name__ == '__main__':
+ unittest.main(defaultTest="test_suite")
+
Property changes on: pymoul/trunk/src/moul/osdependent/tests/test_osdependent.py
___________________________________________________________________
Name: svn:eol-style
+ native
Modified: pymoul/trunk/src/moul/osdependent/win32/__init__.py
===================================================================
--- pymoul/trunk/src/moul/osdependent/win32/__init__.py 2007-01-26 02:16:36 UTC (rev 79)
+++ pymoul/trunk/src/moul/osdependent/win32/__init__.py 2007-01-26 14:17:50 UTC (rev 80)
@@ -22,29 +22,32 @@
__revision__ = "$Revision$"
import os
-#from moul.osdependent.win32.miniwinshell import my_documents
-#from moul.osdependent.win32.miniwinshell import application_data
-from moul.osdependent.win32.winpath import get_homedir
-from moul.osdependent.win32.winpath import get_appdata
+from moul.osdependent.win32.miniwinshell import my_documents as getMyDocuments
+from moul.osdependent.win32.miniwinshell import application_data as getAppdata
+#from moul.osdependent.win32.winpath import get_homedir as getMyDocuments
+#from moul.osdependent.win32.winpath import get_appdata as getAppdata
+from moul.osdependent.win32 import wmi
MOUL_DIR = "Uru Live"
EXEC_NAME = "UruLauncher.exe"
+mycomputer = None
+mydocs = getMyDocuments()
+myappdata = getAppdata()
+
def getMoulUserDataDir():
"""Get path of MOUL data directory
The MOUL data directory contains log files, chatlogs, KI images and many
more things.
"""
- mydoc = get_homedir()
- moul_data = os.path.join(mydoc, MOUL_DIR)
+ moul_data = os.path.join(mydocs, MOUL_DIR)
return moul_data
def getPyMoulDataDir():
"""Get path to the pyMoul ini file
"""
- app_data = get_appdata()
- inidir = os.path.join(app_data, 'pyMoul')
+ inidir = os.path.join(myappdata , 'pyMoul')
return inidir
def _startMOUL(installdir, *args):
@@ -57,3 +60,22 @@
path = os.path.join(installdir, EXEC_NAME)
args = (EXEC_NAME,) + args
return os.spawnv(mode, path, args)
+
+def getCurrentPids():
+ """Returns mapping pid -> name
+ """
+ global mycomputer
+ if mycomputer is None:
+ # XXX: extremely slow, also see getCurrentPidNames
+ mycomputer = wmi.WMI()
+ return [process.ProcessId for process in mycomputer.Win32_Process()]
+
+def getCurrentPidNames():
+ """Returns mapping pid -> name
+ """
+ global mycomputer
+ if mycomputer is None:
+ mycomputer = wmi.WMI()
+ return dict([(process.ProcessId, process.Name)
+ for process in mycomputer.Win32_Process()
+ ])
Added: pymoul/trunk/src/moul/osdependent/win32/wmi.py
===================================================================
--- pymoul/trunk/src/moul/osdependent/win32/wmi.py (rev 0)
+++ pymoul/trunk/src/moul/osdependent/win32/wmi.py 2007-01-26 14:17:50 UTC (rev 80)
@@ -0,0 +1,1246 @@
+##
+# wmi - a lightweight Python wrapper around Microsoft's WMI interface
+#
+# Windows Management Instrumentation (WMI) is Microsoft's answer to
+# the DMTF's Common Information Model. It allows you to query just
+# about any conceivable piece of information from any computer which
+# is running the necessary agent and over which have you the
+# necessary authority.
+#
+# The implementation is by means of COM/DCOM and most of the examples
+# assume you're running one of Microsoft's scripting technologies.
+# Fortunately, Mark Hammond's pywin32 has pretty much all you need
+# for a workable Python adaptation. I haven't tried any of the fancier
+# stuff like Async calls and so on, so I don't know if they'd work.
+#
+# Since the COM implementation doesn't give much away to Python
+# programmers, I've wrapped it in some lightweight classes with
+# some getattr / setattr magic to ease the way. In particular:
+#
+# <ul>
+# <li>
+# The _wmi_namespace object itself will determine its classes
+# and allow you to return all instances of any of them by
+# using its name as an attribute. As an additional shortcut,
+# you needn't specify the Win32_; if the first lookup fails
+# it will try again with a Win32_ on the front:
+#
+# <pre class="code">
+# disks = wmi.WMI ().Win32_LogicalDisk ()
+# </pre>
+#
+# In addition, you can specify what would become the WHERE clause
+# as keyword parameters:
+#
+# <pre class="code">
+# fixed_disks = wmi.WMI ().Win32_LogicalDisk (DriveType = 3)
+# </pre>
+# </li>
+#
+# <li>
+# The objects returned by a WMI lookup are wrapped in a Python
+# class which determines their methods and classes and allows
+# you to access them as though they were Python classes. The
+# methods only allow named parameters.
+#
+# <pre class="code">
+# for p in wmi.WMI ().Win32_Process ():
+# if p.Name.lower () == 'notepad.exe':
+# p.Terminate (Result=1)
+# </pre>
+# </li>
+#
+# <li>
+# Doing a print on one of the WMI objects will result in its
+# GetObjectText_ method being called, which usually produces
+# a meaningful printout of current values.
+# The repr of the object will include its full WMI path,
+# which lets you get directly to it if you need to.
+# </li>
+#
+# <li>
+# You can get the associators and references of an object as
+# a list of python objects by calling the associators () and
+# references () methods on a WMI Python object.
+# NB Don't do this on a Win32_ComputerSystem object; it will
+# take all day and kill your machine!
+#
+# <pre class="code">
+# for p in wmi.WMI ().Win32_Process ():
+# if p.Name.lower () == 'notepad.exe':
+# for r in p.references ():
+# print r.Name
+# </pre>
+# </li>
+#
+# <li>
+# WMI classes (as opposed to instances) are first-class
+# objects, so you can get hold of a class, and call
+# its methods or set up a watch against it.
+#
+# <pre class="code">
+# process = wmi.WMI ().Win32_Process
+# process.Create (CommandLine="notepad.exe")
+# </pre>
+#
+# </li>
+#
+# <li>
+# To make it easier to use in embedded systems and py2exe-style
+# executable wrappers, the module will not force early Dispatch.
+# To do this, it uses a handy hack by Thomas Heller for easy access
+# to constants.
+# </li>
+#
+# <li>
+# Typical usage will be:
+#
+# <pre class="code">
+# import wmi
+#
+# vodev1 = wmi.WMI ("vodev1")
+# for disk in vodev1.Win32_LogicalDisk ():
+# if disk.DriveType == 3:
+# space = 100 * long (disk.FreeSpace) / long (disk.Size)
+# print "%s has %d%% free" % (disk.Name, space)
+# </pre>
+# </li>
+#
+# </ul>
+#
+# Many thanks, obviously to Mark Hammond for creating the win32all
+# extensions, but also to Alex Martelli and Roger Upole, whose
+# c.l.py postings pointed me in the right direction.
+# Thanks especially in release 1.2 to Paul Tiemann for his code
+# contributions and robust testing.
+#
+# (c) Tim Golden - mail at timgolden.me.uk 5th June 2003
+# Licensed under the (GPL-compatible) MIT License:
+# http://www.opensource.org/licenses/mit-license.php
+#
+# For change history see CHANGELOG.TXT
+##
+try:
+ True, False
+except NameError:
+ True = 1
+ False = 0
+
+try:
+ object
+except NameError:
+ class object: pass
+
+__VERSION__ = "1.2.1"
+
+_DEBUG = False
+
+import sys
+import re
+from win32com.client import GetObject, Dispatch
+import pywintypes
+
+class ProvideConstants (object):
+ """
+ A class which, when called on a win32com.client.Dispatch object,
+ provides lazy access to constants defined in the typelib.
+
+ They can be accessed as attributes of the _constants property.
+ From Thomas Heller on c.l.py
+ """
+ def __init__(self, comobj):
+ "@param comobj A COM object whose typelib constants are to be exposed"
+ comobj.__dict__["_constants"] = self
+ # Get the typelibrary's typecomp interface
+ self.__typecomp = \
+ comobj._oleobj_.GetTypeInfo().GetContainingTypeLib()[0].GetTypeComp()
+
+ def __getattr__(self, name):
+ if name.startswith("__") and name.endswith("__"):
+ raise AttributeError, name
+ result = self.__typecomp.Bind(name)
+ # Bind returns a 2-tuple, first item is TYPEKIND,
+ # the second item has the value
+ if not result[0]:
+ raise AttributeError, name
+ return result[1].value
+
+obj = GetObject ("winmgmts:")
+ProvideConstants (obj)
+
+wbemErrInvalidQuery = obj._constants.wbemErrInvalidQuery
+wbemErrTimedout = obj._constants.wbemErrTimedout
+wbemFlagReturnImmediately = obj._constants.wbemFlagReturnImmediately
+wbemFlagForwardOnly = obj._constants.wbemFlagForwardOnly
+
+def handle_com_error (error_info):
+ """Convenience wrapper for displaying all manner of COM errors.
+ Raises a x_wmi exception with more useful information attached
+
+ @param error_info The structure attached to a pywintypes.com_error
+ """
+ hresult_code, hresult_name, additional_info, parameter_in_error = error_info
+ exception_string = ["%s - %s" % (hex (hresult_code), hresult_name)]
+ if additional_info:
+ wcode, source_of_error, error_description, whlp_file, whlp_context, scode = additional_info
+ exception_string.append (" Error in: %s" % source_of_error)
+ exception_string.append (" %s - %s" % (hex (scode), error_description.strip ()))
+ raise x_wmi, "\n".join (exception_string)
+
+def from_time (year=None, month=None, day=None, hours=None, minutes=None, seconds=None, microseconds=None, timezone=None):
+ """
+ Convenience wrapper to take a series of date/time elements and return a WMI time
+ of the form yyyymmddHHMMSS.mmmmmm+UUU. All elements may be int, string or
+ omitted altogether. If omitted, they will be replaced in the output string
+ by a series of stars of the appropriate length.
+
+ @param year The year element of the date/time
+ @param month The month element of the date/time
+ @param day The day element of the date/time
+ @param hours The hours element of the date/time
+ @param minutes The minutes element of the date/time
+ @param seconds The seconds element of the date/time
+ @param microseconds The microseconds element of the date/time
+ @param timezone The timeezone element of the date/time
+
+ @return A WMI datetime string of the form: yyyymmddHHMMSS.mmmmmm+UUU
+ """
+ def str_or_stars (i, length):
+ if i is None:
+ return "*" * length
+ else:
+ return str (i).rjust (length, "0")
+
+ wmi_time = ""
+ wmi_time += str_or_stars (year, 4)
+ wmi_time += str_or_stars (month, 2)
+ wmi_time += str_or_stars (day, 2)
+ wmi_time += str_or_stars (hours, 2)
+ wmi_time += str_or_stars (minutes, 2)
+ wmi_time += str_or_stars (seconds, 2)
+ wmi_time += "."
+ wmi_time += str_or_stars (microseconds, 6)
+ wmi_time += str_or_stars (timezone, 4)
+
+ return wmi_time
+
+def to_time (wmi_time):
+ """
+ Convenience wrapper to take a WMI datetime string of the form
+ yyyymmddHHMMSS.mmmmmm+UUU and return a 9-tuple containing the
+ individual elements, or None where string contains placeholder
+ stars.
+
+ @param wmi_time The WMI datetime string in yyyymmddHHMMSS.mmmmmm+UUU format
+
+ @return A 9-tuple of (year, month, day, hours, minutes, seconds, microseconds, timezone)
+ """
+ def int_or_none (s, start, end):
+ try:
+ return int (s[start:end])
+ except ValueError:
+ return None
+
+ year = int_or_none (wmi_time, 0, 4)
+ month = int_or_none (wmi_time, 4, 6)
+ day = int_or_none (wmi_time, 6, 8)
+ hours = int_or_none (wmi_time, 8, 10)
+ minutes = int_or_none (wmi_time, 10, 12)
+ seconds = int_or_none (wmi_time, 12, 14)
+ microseconds = int_or_none (wmi_time, 15, 21)
+ timezone = wmi_time[21:]
+
+ return year, month, day, hours, minutes, seconds, microseconds, timezone
+
+#
+# Exceptions
+#
+class x_wmi (Exception):
+ pass
+
+class x_wmi_invalid_query (x_wmi):
+ pass
+
+class x_wmi_timed_out (x_wmi):
+ pass
+
+class x_wmi_no_namespace (x_wmi):
+ pass
+
+WMI_EXCEPTIONS = {
+ wbemErrInvalidQuery : x_wmi_invalid_query,
+ wbemErrTimedout : x_wmi_timed_out
+}
+
+def _set (obj, attribute, value):
+ """
+ Helper function to add an attribute directly into the instance
+ dictionary, bypassing possible __getattr__ calls
+
+ @param obj Any python object
+ @param attribute String containing attribute name
+ @param value Any python object
+ """
+ obj.__dict__[attribute] = value
+
+class _wmi_method:
+ """
+ A currying sort of wrapper around a WMI method name. It
+ abstract's the method's parameters and can be called like
+ a normal Python object passing in the parameter values.
+
+ Output parameters are returned from the call as a tuple.
+ In addition, the docstring is set up as the method's
+ signature, including an indication as to whether any
+ given parameter is expecting an array, and what
+ special privileges are required to call the method.
+ """
+
+ def __init__ (self, ole_object, method_name):
+ """
+ @param ole_object The WMI class/instance whose method is to be called
+ @param method_name The name of the method to be called
+ """
+ try:
+ self.ole_object = Dispatch (ole_object)
+ self.method = ole_object.Methods_ (method_name)
+ self.qualifiers = {}
+ for q in self.method.Qualifiers_:
+ self.qualifiers[q.Name] = q.Value
+ self.provenance = "\n".join (self.qualifiers.get ("MappingStrings", []))
+
+ self.in_parameters = self.method.InParameters
+ self.out_parameters = self.method.OutParameters
+ if self.in_parameters is None:
+ self.in_parameter_names = []
+ else:
+ self.in_parameter_names = [(i.Name, i.IsArray) for i in self.in_parameters.Properties_]
+ if self.out_parameters is None:
+ self.out_parameter_names = []
+ else:
+ self.out_parameter_names = [(i.Name, i.IsArray) for i in self.out_parameters.Properties_]
+
+ doc = "%s (%s) => (%s)" % (
+ method_name,
+ ", ".join ([name + ("", "[]")[is_array] for (name, is_array) in self.in_parameter_names]),
+ ", ".join ([name + ("", "[]")[is_array] for (name, is_array) in self.out_parameter_names])
+ )
+ privileges = self.qualifiers.get ("Privileges", [])
+ if privileges:
+ doc += " | Needs: " + ", ".join (privileges)
+ self.__doc__ = doc
+ except pywintypes.com_error, error_info:
+ handle_com_error (error_info)
+
+ def __call__ (self, **kwargs):
+ """
+ Execute the call to a WMI method, returning
+ a tuple (even if is of only one value) containing
+ the out and return parameters.
+ """
+ try:
+ if self.in_parameters:
+ parameter_names = {}
+ for name, is_array in self.in_parameter_names:
+ parameter_names[name] = is_array
+
+ parameters = self.in_parameters
+ for k, v in kwargs.items ():
+ is_array = parameter_names.get (k)
+ if is_array is None:
+ raise AttributeError, "%s is not a valid parameter for %s" % (k, self.__doc__)
+ else:
+ if is_array:
+ try: list (v)
+ except TypeError: raise TypeError, "%s must be iterable" % k
+
+ parameters.Properties_ (k).Value = v
+
+ result = self.ole_object.ExecMethod_ (self.method.Name, self.in_parameters)
+ else:
+ result = self.ole_object.ExecMethod_ (self.method.Name)
+
+ results = []
+ for name, is_array in self.out_parameter_names:
+ value = result.Properties_ (name).Value
+ if is_array:
+ #
+ # Thanks to Jonas Bjering for bug report and path
+ #
+ results.append (list (value or []))
+ else:
+ results.append (value)
+ return tuple (results)
+
+ except pywintypes.com_error, error_info:
+ handle_com_error (error_info)
+
+ def __repr__ (self):
+ return "<function %s>" % self.__doc__
+
+#
+# class _wmi_object
+#
+class _wmi_object:
+ "A lightweight wrapper round an OLE WMI object"
+
+ def __init__ (self, ole_object, instance_of=None, fields=[]):
+ try:
+ _set (self, "ole_object", ole_object)
+ _set (self, "_instance_of", instance_of)
+ _set (self, "properties", {})
+ _set (self, "methods", {})
+
+ if self._instance_of:
+ if fields:
+ for field in fields:
+ self.properties[field] = None
+ else:
+ _set (self, "properties", self._instance_of.properties.copy ())
+ _set (self, "methods", self._instance_of.methods)
+ else:
+ for p in ole_object.Properties_:
+ self.properties[p.Name] = None
+ for m in ole_object.Methods_:
+ self.methods[m.Name] = None
+
+ _set (self, "_properties", self.properties.keys ())
+ _set (self, "_methods", self.methods.keys ())
+
+ _set (self, "qualifiers", {})
+ for q in self.ole_object.Qualifiers_:
+ self.qualifiers[q.Name] = q.Value
+ _set (self, "is_association", self.qualifiers.has_key ("Association"))
+
+ except pywintypes.com_error, error_info:
+ handle_com_error (error_info)
+
+ def __str__ (self):
+ """
+ For a call to print [object] return the OLE description
+ of the properties / values of the object
+ """
+ try:
+ return self.ole_object.GetObjectText_ ()
+ except pywintypes.com_error, error_info:
+ handle_com_error (error_info)
+
+ def __repr__ (self):
+ """
+ Indicate both the fact that this is a wrapped WMI object
+ and the WMI object's own identifying class.
+ """
+ try:
+ return "<%s: %s>" % (self.__class__.__name__, str (self.Path_.Path))
+ except pywintypes.com_error, error_info:
+ handle_com_error (error_info)
+
+ def _cached_properties (self, attribute):
+ if self.properties[attribute] is None:
+ self.properties[attribute] = self.ole_object.Properties_ (attribute)
+ return self.properties[attribute]
+
+ def _cached_methods (self, attribute):
+ if self.methods[attribute] is None:
+ self.methods[attribute] = _wmi_method (self.ole_object, attribute)
+ return self.methods[attribute]
+
+ def __getattr__ (self, attribute):
+ """
+ Attempt to pass attribute calls to the proxied COM object.
+ If the attribute is recognised as a property, return its value;
+ if it is recognised as a method, return a method wrapper which
+ can then be called with parameters; otherwise pass the lookup
+ on to the underlying object.
+ """
+ try:
+ if self.properties.has_key (attribute):
+ value = self._cached_properties (attribute).Value
+ #
+ # If this is an association, its properties are
+ # actually the paths to the two aspects of the
+ # association, so translate them automatically
+ # into WMI objects.
+ #
+ if self.is_association:
+ return WMI (moniker=value)
+ else:
+ return value
+ elif self.methods.has_key (attribute):
+ return self._cached_methods (attribute)
+ else:
+ return getattr (self.ole_object, attribute)
+ except pywintypes.com_error, error_info:
+ handle_com_error (error_info)
+
+ def __setattr__ (self, attribute, value):
+ """
+ If the attribute to be set is valid for the proxied
+ COM object, set that objects's parameter value; if not,
+ raise an exception.
+ """
+ try:
+ if self.properties.has_key (attribute):
+ self._cached_properties (attribute).Value = value
+ if self.ole_object.Path_.Path:
+ self.ole_object.Put_ ()
+ else:
+ raise AttributeError, attribute
+ except pywintypes.com_error, error_info:
+ handle_com_error (error_info)
+
+ def __eq__ (self, other):
+ """
+ Use WMI's CompareTo_ to compare this object with
+ another. Don't try to do anything if the other
+ object is not a wmi object. It might be possible
+ to compare this object's unique key with a string
+ or something, but this doesn't seem to be universal
+ enough to merit a special case.
+ """
+ if isinstance (other, self.__class__):
+ return self.ole_object.CompareTo_ (other.ole_object)
+ else:
+ raise x_wmi, "Can't compare a WMI object with something else"
+
+ def put (self):
+ self.ole_object.Put_ ()
+
+ def set (self, **kwargs):
+ """
+ Set several properties of the underlying object
+ at one go. This is particularly useful in combination
+ with the new () method below. However, an instance
+ which has been spawned in this way won't have enough
+ information to write pack, so only try if the
+ instance has a path.
+ """
+ if kwargs:
+ try:
+ for attribute, value in kwargs.items ():
+ if self.properties.has_key (attribute):
+ self._cached_properties (attribute).Value = value
+ else:
+ raise AttributeError, attribute
+ #
+ # Only try to write the attributes
+ # back if the object exists.
+ #
+ if self.ole_object.Path_.Path:
+ self.ole_object.Put_ ()
+ except pywintypes.com_error, error_info:
+ handle_com_error (error_info)
+
+ def path (self):
+ """
+ Return the WMI URI to this object. Can be used to
+ determine the path relative to the parent namespace. eg,
+
+ <pre class="code">
+ pp0 = wmi.WMI ().Win32_ParallelPort ()[0]
+ print pp0.path ().RelPath
+ </pre>
+ """
+ try:
+ return self.ole_object.Path_
+ except pywintypes.com_error, error_info:
+ handle_com_error (error_info)
+
+ def derivation (self):
+ """Return a tuple representing the object derivation for
+ this object, with the most specific object first. eg,
+
+ pp0 = wmi.WMI ().Win32_ParallelPort ()[0]
+ print ' <- '.join (pp0.derivation ())
+ """
+ try:
+ return self.ole_object.Derivation_
+ except pywintypes.com_error, error_info:
+ handle_com_error (error_info)
+
+ def associators (self, wmi_association_class="", wmi_result_class=""):
+ """Return a list of objects related to this one, optionally limited
+ either by association class (ie the name of the class which relates
+ them) or by result class (ie the name of the class which would be
+ retrieved)
+
+ <pre class="code">
+c = wmi.WMI ()
+pp = c.Win32_ParallelPort ()[0]
+
+for i in pp.associators (wmi_association_class="Win32_PortResource"):
+ print i
+
+for i in pp.associators (wmi_result_class="Win32_PnPEntity"):
+ print i
+ </pre>
+ """
+ try:
+ return [
+ _wmi_object (i) for i in \
+ self.ole_object.Associators_ (
+ strAssocClass=wmi_association_class,
+ strResultClass=wmi_result_class
+ )
+ ]
+ except pywintypes.com_error, error_info:
+ handle_com_error (error_info)
+
+ def references (self, wmi_class=""):
+ """Return a list of associations involving this object, optionally
+ limited by the result class (the name of the association class).
+
+ NB Associations are treated specially; although WMI only returns
+ the string corresponding to the instance of each associated object,
+ this module will automatically convert that to the object itself.
+
+ <pre class="code">
+ c = wmi.WMI ()
+ sp = c.Win32_SerialPort ()[0]
+
+ for i in sp.references ():
+ print i
+
+ for i in sp.references (wmi_class="Win32_SerialPortSetting"):
+ print i
+ </pre>
+ """
+ try:
+ return [_wmi_object (i) for i in self.ole_object.References_ (strResultClass=wmi_class)]
+ except pywintypes.com_error, error_info:
+ handle_com_error (error_info)
+
+#
+# class _wmi_class
+#
+class _wmi_class (_wmi_object):
+ """Currying class to assist in issuing queries against
+ a WMI namespace. The idea is that when someone issues
+ an otherwise unknown method against the WMI object, if
+ it matches a known WMI class a query object will be
+ returned which may then be called with one or more params
+ which will form the WHERE clause. eg,
+
+ <pre class="code">
+ c = wmi.WMI ()
+ c_drive = c.Win32_LogicalDisk (Name='C:')
+ </pre>
+ """
+ def __init__ (self, namespace, wmi_class):
+ _wmi_object.__init__ (self, wmi_class)
+ _set (self, "_namespace", namespace)
+ _set (self, "_class_name", wmi_class.Path_.Class)
+
+ def query (self, fields=[], **where_clause):
+ """Make it slightly easier to query against the class,
+ by calling the namespace's query with the class preset.
+ Won't work if the class has been instantiated directly.
+ """
+ if self._namespace is None:
+ raise x_wmi_no_namespace, "You cannot query directly from a WMI class"
+
+ try:
+ field_list = ", ".join (fields) or "*"
+ wql = "SELECT " + field_list + " FROM " + self._class_name
+ if where_clause:
+ wql += " WHERE " + " AND ". join (["%s = '%s'" % (k, v) for k, v in where_clause.items ()])
+ return self._namespace.query (wql, self, fields)
+ except pywintypes.com_error, error_info:
+ handle_com_error (error_info)
+
+ __call__ = query
+
+ def watch_for (
+ self,
+ notification_type=None,
+ delay_secs=1,
+ **where_clause
+ ):
+ if self._namespace is None:
+ raise x_wmi_no_namespace, "You cannot watch directly from a WMI class"
+
+ return self._namespace.watch_for (
+ notification_type=notification_type,
+ wmi_class=self._class_name,
+ delay_secs=delay_secs,
+ **where_clause
+ )
+
+ def instances (self):
+ """Return a list of instances of the WMI class
+ """
+ try:
+ return [_wmi_object (instance, self) for instance in self.Instances_ ()]
+ except pywintypes.com_error, error_info:
+ handle_com_error (error_info)
+
+ def new (self, **kwargs):
+ """This is the equivalent to the raw-WMI SpawnInstance_
+ method. Note that there are relatively few uses for
+ this, certainly fewer than you might imagine. Most
+ classes which need to create a new *real* instance
+ of themselves, eg Win32_Process, offer a .Create
+ method. SpawnInstance_ is generally reserved for
+ instances which are passed as parameters to such
+ .Create methods, a common example being the
+ Win32_SecurityDescriptor, passed to Win32_Share.Create
+ and other instances which need security.
+
+ The example here is Win32_ProcessStartup, which
+ controls the shown/hidden state etc. of a new
+ Win32_Process instance.
+
+ <pre class="code">
+ import win32con
+ import wmi
+ c = wmi.WMI ()
+ startup = c.Win32_ProcessStartup.new (ShowWindow=win32con.SW_SHOWMINIMIZED)
+ pid, retval = c.Win32_Process.Create (
+ CommandLine="notepad.exe",
+ ProcessStartupInformation=startup
+ )
+ </pre>
+
+ NB previous versions of this module, used this function
+ to create new process. This is *not* a good example
+ of its use; it is better handled with something like
+ the example above.
+ """
+ try:
+ obj = _wmi_object (self.SpawnInstance_ (), self)
+ obj.set (**kwargs)
+ return obj
+ except pywintypes.com_error, error_info:
+ handle_com_error (error_info)
+
+#
+# class _wmi_result
+#
+class _wmi_result:
+ """Simple, data only result for targeted WMI queries which request
+ data only result classes via fetch_as_classes.
+ """
+ def __init__(self, obj, attributes):
+ if attributes:
+ for attr in attributes:
+ self.__dict__[attr] = obj.Properties_ (attr).Value
+ else:
+ for p in obj.Properties_:
+ attr = p.Name
+ self.__dict__[attr] = obj.Properties_(attr).Value
+
+#
+# class WMI
+#
+class _wmi_namespace:
+ """A WMI root of a computer system. The classes attribute holds a list
+ of the classes on offer. This means you can explore a bit with
+ things like this:
+
+ <pre class="code">
+ c = wmi.WMI ()
+ for i in c.classes:
+ if "user" in i.lower ():
+ print i
+ </pre>
+ """
+ def __init__ (self, namespace, find_classes):
+ _set (self, "_namespace", namespace)
+ #
+ # wmi attribute preserved for backwards compatibility
+ #
+ _set (self, "wmi", namespace)
+
+ # Initialise the "classes" attribute, to avoid infinite recursion in the
+ # __getattr__ method (which uses it).
+ self.classes = {}
+ #
+ # Pick up the list of classes under this namespace
+ # so that they can be queried, and used as though
+ # properties of the namespace by means of the __getattr__
+ # hook below.
+ # If the namespace does not support SubclassesOf, carry on
+ # regardless
+ #
+ if find_classes:
+ try:
+ self.classes.update (self.subclasses_of ())
+ except AttributeError:
+ pass
+
+ def __repr__ (self):
+ return "<_wmi_namespace: %s>" % self.wmi
+
+ def __str__ (self):
+ return repr (self)
+
+ def get (self, moniker):
+ try:
+ return _wmi_object (self.wmi.Get (moniker))
+ except pywintypes.com_error, error_info:
+ handle_com_error (error_info)
+
+ def handle (self):
+ """The raw OLE object representing the WMI namespace"""
+ return self._namespace
+
+ def subclasses_of (self, root="", regex=r".*"):
+ classes = {}
+ for c in self._namespace.SubclassesOf (root):
+ klass = c.Path_.Class
+ if re.match (regex, klass):
+ classes[klass] = None
+ return classes
+
+ def instances (self, class_name):
+ """Return a list of instances of the WMI class. This is
+ (probably) equivalent to querying with no qualifiers.
+
+ <pre class="code">
+ system.instances ("Win32_LogicalDisk")
+ # should be the same as
+ system.Win32_LogicalDisk ()
+ </pre>
+ """
+ try:
+ return [_wmi_object (obj) for obj in self._namespace.InstancesOf (class_name)]
+ except pywintypes.com_error, error_info:
+ handle_com_error (error_info)
+
+ def new (self, wmi_class, **kwargs):
+ """This is now implemented by a call to _wmi_namespace.new (qv)"""
+ return getattr (self, wmi_class).new (**kwargs)
+
+ new_instance_of = new
+
+ def _raw_query (self, wql):
+ """Execute a WQL query and return its raw results. Use the flags
+ recommended by Microsoft to achieve a read-only, semi-synchronous
+ query where the time is taken while looping through. Should really
+ be a generator, but ...
+ NB Backslashes need to be doubled up.
+ """
+ flags = wbemFlagReturnImmediately | wbemFlagForwardOnly
+ wql = wql.replace ("\\", "\\\\")
+ if _DEBUG: print "_raw_query(wql):", wql
+ try:
+ return self._namespace.ExecQuery (strQuery=wql, iFlags=flags)
+ except pywintypes.com_error, (hresult, hresult_text, additional, param_in_error):
+ raise WMI_EXCEPTIONS.get (hresult, x_wmi (hresult))
+
+ def query (self, wql, instance_of=None, fields=[]):
+ """Perform an arbitrary query against a WMI object, and return
+ a list of _wmi_object representations of the results.
+ """
+ return [ _wmi_object (obj, instance_of, fields) for obj in self._raw_query(wql) ]
+
+ def fetch_as_classes (self, wmi_classname, fields=(), **where_clause):
+ """Build and execute a wql query to fetch the specified list of fields from
+ the specified wmi_classname + where_clause, then return the results as
+ a list of simple class instances with attributes matching fields_list.
+
+ If fields is left empty, select * and pre-load all class attributes for
+ each class returned.
+ """
+ wql = "SELECT %s FROM %s" % (fields and ", ".join (fields) or "*", wmi_classname)
+ if where_clause:
+ wql += " WHERE " + " AND ".join (["%s = '%s'" % (k, v) for k, v in where_clause.items()])
+ return [_wmi_result (obj, fields) for obj in self._raw_query(wql)]
+
+ def fetch_as_lists (self, wmi_classname, fields, **where_clause):
+ """Build and execute a wql query to fetch the specified list of fields from
+ the specified wmi_classname + where_clause, then return the results as
+ a list of lists whose values correspond fields_list.
+ """
+ wql = "SELECT %s FROM %s" % (", ".join (fields), wmi_classname)
+ if where_clause:
+ wql += " WHERE " + " AND ".join (["%s = '%s'" % (k, v) for k, v in where_clause.items()])
+ results = []
+ for obj in self._raw_query(wql):
+ results.append ([obj.Properties_ (field).Value for field in fields])
+ return results
+
+ def watch_for (
+ self,
+ raw_wql=None,
+ notification_type=None,
+ wmi_class=None,
+ delay_secs=1,
+ **where_clause
+ ):
+ """Set up an event tracker on a WMI event. This function
+ returns an wmi_watcher which can be called to get the
+ next event. eg,
+
+ <pre class="code">
+ c = wmi.WMI ()
+
+ raw_wql = "SELECT * FROM __InstanceCreationEvent WITHIN 2 WHERE TargetInstance ISA 'Win32_Process'"
+ watcher = c.watch_for (raw_wql=raw_wql)
+ while 1:
+ process_created = watcher ()
+ print process_created.Name
+
+ # or
+
+ watcher = c.watch_for (
+ notification_type="Creation",
+ wmi_class="Win32_Process",
+ delay_secs=2,
+ Name='calc.exe'
+ )
+ calc_created = watcher ()
+ </pre>
+
+ Now supports timeout on the call to watcher, eg:
+
+ <pre class="code">
+ import pythoncom
+ import wmi
+ c = wmi.WMI (privileges=["Security"])
+ watcher1 = c.watch_for (
+ notification_type="Creation",
+ wmi_class="Win32_NTLogEvent",
+ Type="error"
+ )
+ watcher2 = c.watch_for (
+ notification_type="Creation",
+ wmi_class="Win32_NTLogEvent",
+ Type="warning"
+ )
+
+ while 1:
+ try:
+ error_log = watcher1 (500)
+ except wmi.x_wmi_timed_out:
+ pythoncom.PumpWaitingMessages ()
+ else:
+ print error_log
+
+ try:
+ warning_log = watcher2 (500)
+ except wmi.x_wmi_timed_out:
+ pythoncom.PumpWaitingMessages ()
+ else:
+ print warning_log
+ </pre>
+ """
+ class_name = wmi_class
+ if raw_wql:
+ wql = raw_wql
+ else:
+ if where_clause:
+ where = " AND " + " AND ".join (["TargetInstance.%s = '%s'" % (k, v) for k, v in where_clause.items ()])
+ else:
+ where = ""
+ wql = \
+ "SELECT * FROM __Instance%sEvent WITHIN %d WHERE TargetInstance ISA '%s' %s" % \
+ (notification_type, delay_secs, class_name, where)
+
+ if _DEBUG: print wql
+
+ try:
+ return _wmi_watcher (self._namespace.ExecNotificationQuery (wql))
+ except pywintypes.com_error, error_info:
+ handle_com_error (error_info)
+
+ def __getattr__ (self, attribute):
+ """Offer WMI classes as simple attributes. Pass through any untrapped
+ unattribute to the underlying OLE object. This means that new or
+ unmapped functionality is still available to the module user.
+ """
+ #
+ # Don't try to match against known classes as was previously
+ # done since the list may not have been requested
+ # (find_classes=False).
+ #
+ try:
+ return self._cached_classes (attribute)
+ except pywintypes.com_error, error_i...
[truncated message content] |
|
From: <ti...@us...> - 2007-01-26 02:16:38
|
Revision: 79
http://pymoul.svn.sourceforge.net/pymoul/?rev=79&view=rev
Author: tiran
Date: 2007-01-25 18:16:36 -0800 (Thu, 25 Jan 2007)
Log Message:
-----------
Lot's of changes:
Cleanup logging
New singleapp module added
Restrict to one instance of moulqt
Modified Paths:
--------------
pymoul/trunk/src/moul/config/__init__.py
pymoul/trunk/src/moul/file/tests/test_localization.py
pymoul/trunk/src/moul/file/wdysini.py
pymoul/trunk/src/moul/log.py
pymoul/trunk/src/moul/qt/moulqt.py
pymoul/trunk/src/moul/qt/ui/mainwindow.py
Added Paths:
-----------
pymoul/trunk/src/moul/osdependent/singleapp.py
pymoul/trunk/src/moul/osdependent/tests/
pymoul/trunk/src/moul/osdependent/tests/__init__.py
pymoul/trunk/src/moul/osdependent/tests/test_singleapp.py
Modified: pymoul/trunk/src/moul/config/__init__.py
===================================================================
--- pymoul/trunk/src/moul/config/__init__.py 2007-01-25 18:54:52 UTC (rev 78)
+++ pymoul/trunk/src/moul/config/__init__.py 2007-01-26 02:16:36 UTC (rev 79)
@@ -19,8 +19,9 @@
"""
import os
import sys
+from logging import getLogger
-from moul.log import LOG
+LOG = getLogger('pyMoul')
# a program under py2exe is sys.frozen
__FROZEN__ = bool(getattr(sys, 'frozen', False))
Modified: pymoul/trunk/src/moul/file/tests/test_localization.py
===================================================================
--- pymoul/trunk/src/moul/file/tests/test_localization.py 2007-01-25 18:54:52 UTC (rev 78)
+++ pymoul/trunk/src/moul/file/tests/test_localization.py 2007-01-26 02:16:36 UTC (rev 79)
@@ -41,13 +41,13 @@
def test_parseLocDir(self):
parseLocDirectory(base)
- key = (u'testage', u'testset', u'testelement', u'english')
+ key = (u'english', u'testage', u'testset', u'testelement')
self.failUnless(key in translationRegistry, translationRegistry.keys())
self.failUnlessEqual(len(translationRegistry), 1)
def test_parseLoc(self):
parseLoc(os.path.join(base, 'test.loc'))
- key = (u'testage', u'testset', u'testelement', u'english')
+ key = (u'english', u'testage', u'testset', u'testelement')
self.failUnless(key in translationRegistry, translationRegistry.keys())
self.failUnlessEqual(len(translationRegistry), 1)
Modified: pymoul/trunk/src/moul/file/wdysini.py
===================================================================
--- pymoul/trunk/src/moul/file/wdysini.py 2007-01-25 18:54:52 UTC (rev 78)
+++ pymoul/trunk/src/moul/file/wdysini.py 2007-01-26 02:16:36 UTC (rev 79)
@@ -161,7 +161,7 @@
Constrain() is a NOOP
>>> c = Constrain('foo', False, object)
- >>> c('dummy')
+ >>> c('dummy', debug="name")
'dummy'
"""
__slots__ = ()
@@ -175,21 +175,21 @@
"""Min / max constrain
>>> c = MinMax(1, 10)
- >>> c(1)
+ >>> c(1, debug="name")
1
- >>> c(10)
+ >>> c(10, debug="name")
10
- >>> c(11)
+ >>> c(11, debug="name")
Traceback (most recent call last):
...
- ConstrainError: 11 > max 10
- >>> c(-1)
+ ConstrainError: name: 11 > max 10
+ >>> c(-1, debug="name")
Traceback (most recent call last):
...
- ConstrainError: -1 < min 1
+ ConstrainError: name: -1 < min 1
>>> c = MinMax(0, 1)
- >>> c(0.5)
+ >>> c(0.5, debug="name")
0.5
"""
__slots__ = ('_min', '_max')
@@ -210,16 +210,16 @@
"""Constrain for video mode indexes
>>> v = VideoConstrain()
- >>> v(0)
+ >>> v(0, debug="name")
0
- >>> v(-1)
+ >>> v(-1, debug="name")
Traceback (most recent call last):
...
- ConstrainError: -1 < min 0
- >>> v(11)
+ ConstrainError: name: -1 < min 0
+ >>> v(11, debug="name")
Traceback (most recent call last):
...
- ConstrainError: 11 > max 10
+ ConstrainError: name: 11 > max 10
"""
def __init__(self):
self._min = 0
@@ -229,12 +229,12 @@
"""value in list constrain
>>> c = Contains((1, 2, 3))
- >>> c(1)
+ >>> c(1, debug="name")
1
- >>> c(4)
+ >>> c(4, debug="name")
Traceback (most recent call last):
...
- ConstrainError: 4 not in (1, 2, 3)
+ ConstrainError: name: 4 not in (1, 2, 3)
"""
__slots__ = ('_values')
def __init__(self, values):
Modified: pymoul/trunk/src/moul/log.py
===================================================================
--- pymoul/trunk/src/moul/log.py 2007-01-25 18:54:52 UTC (rev 78)
+++ pymoul/trunk/src/moul/log.py 2007-01-26 02:16:36 UTC (rev 79)
@@ -27,17 +27,23 @@
import sys
import platform
import logging
+from logging import Formatter
from logging import handlers
-
from moul.metadata import __version__ as moul_version
-# alias
getLogger = logging.getLogger
# copied from moul.config to prevent circular imports
__FROZEN__ = bool(getattr(sys, 'frozen', False))
__LOG_SIGNALS__ = not __FROZEN__
+format = Formatter('%(asctime)s %(name)-8s %(levelname)-7s %(message)s',
+ #'%a, %d %b %Y %H:%M:%S'
+ '%m-%d %H:%M:%S')
+root = getLogger()
+root.setLevel(logging.DEBUG)
+LOG = getLogger('pyMoul')
+
class LoggingStdout(object):
"""Replacement for stdout/stderr IO
"""
@@ -52,18 +58,50 @@
if value:
self._logfunc(value)
-format = logging.Formatter('%(asctime)s %(name)-8s %(levelname)-7s %(message)s',
- #'%a, %d %b %Y %H:%M:%S'
- '%m-%d %H:%M:%S')
-root = getLogger()
-root.setLevel(logging.DEBUG)
+mhdlr = None
+fhdlr = None
+def _installMemoryHdlr():
+ """setup a memory handler to store records before we have the
+ infrastructure to log events to a file
+ """
+ global mhdlr
+ mhdlr = handlers.MemoryHandler(capacity=4*1024) # MemoryHandler doesn't flush w/o a target
+ mhdlr.setFormatter(format)
+ root.addHandler(mhdlr)
-# setup a memory handler to store records before we have the infrastructure
-# to log events to a file
-mhdlr = handlers.MemoryHandler(capacity=16*1024) # MemoryHandler doesn't flush w/o a target
-mhdlr.setFormatter(format)
-root.addHandler(mhdlr)
+def _removeMemoryHdlr():
+ """Remove memory handler
+ """
+ global mhdlr
+ global fhdlr
+ mhdlr.setTarget(fhdlr)
+ mhdlr.flush()
+ root.removeHandler(mhdlr)
+ del mhdlr
+def _installFileHdlr():
+ """Install a file handler
+ """
+ global fhdlr
+ from moul.config import getPyMoulDataDir
+ logFile = os.path.join(getPyMoulDataDir(check=True), 'pymoul.log')
+ LOG.debug("Adding file logger: %s" % logFile)
+ fhdlr = handlers.RotatingFileHandler(logFile, backupCount=9)
+ fhdlr.setFormatter(format)
+ root.addHandler(fhdlr)
+ fhdlr.doRollover()
+
+def _systemInfo():
+ LOG.debug("pyMoul version: %s" % moul_version)
+ LOG.debug("Python: %s" % repr(sys.version_info))
+ LOG.debug("Python: %s" % sys.version.replace('\n', ' '))
+ LOG.debug("Platform: %s, OS name: %s" % (sys.platform, os.name))
+ LOG.debug("system %r, node %r, release %r, version %r, machine %r, processor %r"
+ % platform.uname())
+ LOG.debug("platform name: %s" % platform.platform(True))
+
+# no setup the logging stuff!
+
if not __FROZEN__:
# Add streaming handler to sys.stderr.
# Only log to stderr when the program is not frozen!
@@ -71,37 +109,14 @@
shdlr.setFormatter(format)
root.addHandler(shdlr)
else:
+ _installMemoryHdlr()
# Redirect stdout and stderr to logger when running as frozen app
sys.stdout = LoggingStdout(getLogger('stdout').info)
- print "Stdout redirected"
sys.stderr = LoggingStdout(getLogger('stderr').error)
- print >>sys.stderr, "Stderr redirected"
+ _systemInfo()
+ _installFileHdlr()
+ _removeMemoryHdlr()
-# DEBUG system infos
-LOG = getLogger('pyMoul')
-LOG.debug("pyMoul version: %s" % moul_version)
-LOG.debug("Python: %s" % repr(sys.version_info))
-LOG.debug("Python: %s" % sys.version.replace('\n', ' '))
-LOG.debug("Platform: %s, OS name: %s" % (sys.platform, os.name))
-LOG.debug("system %r, node %r, release %r, version %r, machine %r, processor %r"
- % platform.uname())
-LOG.debug("platform name: %s" % platform.platform(True))
-
-# now get the pymoul userdata dir
-from moul.config import getPyMoulDataDir
-logFile = os.path.join(getPyMoulDataDir(check=True), 'pymoul.log')
-LOG.debug("Adding file logger: %s" % logFile)
-fhdlr = handlers.RotatingFileHandler(logFile, backupCount=9)
-fhdlr.setFormatter(format)
-root.addHandler(fhdlr)
-fhdlr.doRollover()
-
-# flush and remove memory handler
-mhdlr.setTarget(fhdlr)
-mhdlr.flush()
-root.removeHandler(mhdlr)
-del mhdlr
-
def signalLogDecorator(__logger__):
"""Decorator to log signals
Added: pymoul/trunk/src/moul/osdependent/singleapp.py
===================================================================
--- pymoul/trunk/src/moul/osdependent/singleapp.py (rev 0)
+++ pymoul/trunk/src/moul/osdependent/singleapp.py 2007-01-26 02:16:36 UTC (rev 79)
@@ -0,0 +1,184 @@
+# 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
+#
+"""Simple single instance application
+
+Includes portalocker code with minor tweaks for Python 2.4+
+ Author: Jonathan Feinberg <jd...@po...>
+ Version: $Id: portalocker.py,v 1.3 2001/05/29 18:47:55 Administrator Exp $
+ http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/65203
+
+Boiler plate
+>>> import sys
+>>> from shutil import rmtree
+>>> from subprocess import call
+>>> tmpdir = tempfile.mkdtemp()
+>>> testfile = os.path.join(tmpdir, 'test.lck')
+>>> if os.name == 'nt':
+... rm = "del"
+... else:
+... rm = "rm"
+
+Create a file and lock it for this process
+>>> flags = LOCK_SH | LOCK_NB
+>>> fd1 = open(testfile, 'w')
+>>> fn1 = fd1.fileno()
+>>> lock(fd1, flags)
+>>> fd1.write('testdata')
+
+Try to delete the file from another process
+>>> try:
+... retcode = call("%s %s" % (rm, testfile))
+... except:
+... typ, value, tb = sys.exc_info()
+... del tb
+... else:
+... print "Should have raised an error!"
+
+On Windows the error is WindowsError based on OSError
+>>> issubclass(typ, OSError) or typ
+True
+
+Clean up
+>>> unlock(fd1)
+>>> fd1.close()
+>>> rmtree(tmpdir)
+
+>>> singleapp = SimpleSingleApp('testapp')
+>>> lckfile = singleapp.lckfile
+>>> if os.path.isfile(lckfile):
+... os.unlink(fpath)
+>>> path, pid = singleapp.acquire()
+>>> path == lckfile
+True
+>>> os.path.isfile(lckfile)
+True
+>>> singleapp.checkLocked() is None
+True
+>>> singleapp.release()
+>>> os.path.isfile(lckfile)
+False
+"""
+__author__ = "Christian Heimes"
+__version__ = "$Id$"
+__revision__ = "$Revision$"
+
+import os
+import getpass
+import tempfile
+import atexit
+
+TEMPDIR = tempfile.gettempdir()
+USER = getpass.getuser()
+PID = os.getpid()
+
+if os.name == 'nt':
+ import win32con
+ import win32file
+ import pywintypes
+ LOCK_EX = win32con.LOCKFILE_EXCLUSIVE_LOCK
+ LOCK_SH = 0 # the default
+ LOCK_NB = win32con.LOCKFILE_FAIL_IMMEDIATELY
+ lowbits, highbits = 0, -65536
+elif os.name == 'posix':
+ import fcntl
+ LOCK_EX = fcntl.LOCK_EX
+ LOCK_SH = fcntl.LOCK_SH
+ LOCK_NB = fcntl.LOCK_NB
+else:
+ raise RuntimeError("PortaLocker only defined for nt and posix platforms")
+
+if os.name == 'nt':
+ def lock(file, flags):
+ hfile = win32file._get_osfhandle(file.fileno())
+ return win32file.LockFileEx(hfile, flags, lowbits, highbits, pywintypes.OVERLAPPED())
+ def unlock(file):
+ hfile = win32file._get_osfhandle(file.fileno())
+ return win32file.UnlockFileEx(hfile, lowbits, highbits, pywintypes.OVERLAPPED())
+elif os.name =='posix':
+ def lock(file, flags):
+ return fcntl.flock(file.fileno(), flags)
+ def unlock(file):
+ return fcntl.flock(file.fileno(), fcntl.LOCK_UN)
+
+class SingleAppError(OSError):
+ pass
+
+class SimpleSingleApp(object):
+ """A simple single instance application implemementation
+ """
+ flags = LOCK_SH | LOCK_NB
+
+ def __init__(self, appname, path=TEMPDIR, user=USER, pid=PID, ext='.lck',
+ *args):
+ self.appname = appname
+ self.user = user
+ self.path = path
+ self.args = args
+ self.pid = pid
+ self.ext = ext
+ self._fd = None
+ self.lckfile = self._genFilename()
+ # register atexit function
+ atexit.register(self.release)
+
+ def acquire(self):
+ """Acquire lock
+
+ May raise an OSError
+ """
+ try:
+ self._fd = open(self.lckfile, 'w')
+ self._fd.write(str(self.pid))
+ self._fd.flush()
+ lock(self._fd, self.flags)
+ except (OSError, IOError):
+ self._fd.close()
+ self._fd = None
+ raise SingleAppError("Another instance is already running")
+ return self.lckfile, self.pid
+
+ def release(self):
+ """Release lock
+ """
+ try:
+ unlock(self._fd)
+ except (SystemError, SyntaxError):
+ raise
+ except:
+ pass
+ if self._fd:
+ self._fd.close()
+ if os.path.isfile(self.lckfile):
+ os.unlink(self.lckfile)
+
+ def checkLocked(self):
+ """Check if another process has a lock
+ """
+ try:
+ fd = open(self.lckfile, 'a+')
+ fd.close()
+ except OSError:
+ return True
+ else:
+ if self._fd:
+ return None
+ return False
+
+ def _genFilename(self):
+ fname = '_'.join((self.appname, self.user,) + self.args) + self.ext
+ return os.path.join(self.path, fname)
Property changes on: pymoul/trunk/src/moul/osdependent/singleapp.py
___________________________________________________________________
Name: svn:eol-style
+ native
Added: pymoul/trunk/src/moul/osdependent/tests/__init__.py
===================================================================
--- pymoul/trunk/src/moul/osdependent/tests/__init__.py (rev 0)
+++ pymoul/trunk/src/moul/osdependent/tests/__init__.py 2007-01-26 02:16:36 UTC (rev 79)
@@ -0,0 +1,22 @@
+# 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
+#
+"""
+"""
+__author__ = "Christian Heimes"
+__version__ = "$Id$"
+__revision__ = "$Revision$"
Property changes on: pymoul/trunk/src/moul/osdependent/tests/__init__.py
___________________________________________________________________
Name: svn:eol-style
+ native
Added: pymoul/trunk/src/moul/osdependent/tests/test_singleapp.py
===================================================================
--- pymoul/trunk/src/moul/osdependent/tests/test_singleapp.py (rev 0)
+++ pymoul/trunk/src/moul/osdependent/tests/test_singleapp.py 2007-01-26 02:16:36 UTC (rev 79)
@@ -0,0 +1,39 @@
+# 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
+#
+"""moul.osdependent.singleapp
+"""
+__author__ = "Christian Heimes"
+__version__ = "$Id$"
+__revision__ = "$Revision$"
+
+import unittest
+from doctest import DocTestSuite
+
+from moul.osdependent.singleapp import SimpleSingleApp
+from moul.osdependent.singleapp import lock
+from moul.osdependent.singleapp import unlock
+from moul.osdependent.singleapp import LOCK_EX, LOCK_SH, LOCK_NB
+
+def test_suite():
+ return unittest.TestSuite((
+ DocTestSuite('moul.osdependent.singleapp'),
+ ))
+
+if __name__ == '__main__':
+ unittest.main(defaultTest="test_suite")
+
Property changes on: pymoul/trunk/src/moul/osdependent/tests/test_singleapp.py
___________________________________________________________________
Name: svn:eol-style
+ native
Modified: pymoul/trunk/src/moul/qt/moulqt.py
===================================================================
--- pymoul/trunk/src/moul/qt/moulqt.py 2007-01-25 18:54:52 UTC (rev 78)
+++ pymoul/trunk/src/moul/qt/moulqt.py 2007-01-26 02:16:36 UTC (rev 79)
@@ -27,9 +27,24 @@
from PyQt4 import QtGui
from moul.qt.mainwindow import MainWindow
+from moul.osdependent.singleapp import SimpleSingleApp
+from moul.config import getPyMoulDataDir
def main(*args):
app = QtGui.QApplication(*args)
+ singleapp = SimpleSingleApp('pymoulqt', path=getPyMoulDataDir())
+ try:
+ singleapp.acquire()
+ except OSError:
+ mb = QtGui.QMessageBox()
+ mb.setWindowIcon(QtGui.QIcon(":/resources/uru_icon_32x32.png"))
+ mb.setIcon(QtGui.QMessageBox.Critical)
+ mb.setWindowTitle(app.trUtf8("Already running"))
+ mb.setText(app.trUtf8("""An instance of pyMoul QT is already running!"""))
+ mb.setStandardButtons(QtGui.QMessageBox.Close)
+ mb.exec_()
+ sys.exit(1)
+
mainWindow = MainWindow()
mainWindow.show()
return app.exec_()
Modified: pymoul/trunk/src/moul/qt/ui/mainwindow.py
===================================================================
--- pymoul/trunk/src/moul/qt/ui/mainwindow.py 2007-01-25 18:54:52 UTC (rev 78)
+++ pymoul/trunk/src/moul/qt/ui/mainwindow.py 2007-01-26 02:16:36 UTC (rev 79)
@@ -2,7 +2,7 @@
# Form implementation generated from reading ui file 'src\moul\qt\ui\mainwindow.ui'
#
-# Created: Thu Jan 25 19:53:15 2007
+# Created: Thu Jan 25 19:55:32 2007
# by: PyQt4 UI code generator 4.1.1
#
# WARNING! All changes made in this file will be lost!
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <ti...@us...> - 2007-01-25 18:54:52
|
Revision: 78
http://pymoul.svn.sourceforge.net/pymoul/?rev=78&view=rev
Author: tiran
Date: 2007-01-25 10:54:52 -0800 (Thu, 25 Jan 2007)
Log Message:
-----------
Doc tab no works only on my computer - infrastructure isn't present
Modified Paths:
--------------
pymoul/trunk/src/moul/qt/localization.py
pymoul/trunk/src/moul/qt/mainwindow.py
pymoul/trunk/src/moul/qt/ui/mainwindow.py
pymoul/trunk/src/moul/qt/ui/mainwindow.ui
Modified: pymoul/trunk/src/moul/qt/localization.py
===================================================================
--- pymoul/trunk/src/moul/qt/localization.py 2007-01-25 18:50:37 UTC (rev 77)
+++ pymoul/trunk/src/moul/qt/localization.py 2007-01-25 18:54:52 UTC (rev 78)
@@ -22,6 +22,7 @@
__revision__ = "$Revision$"
import sys
+import os
from PyQt4 import QtGui
from PyQt4 import QtCore
@@ -45,8 +46,12 @@
"""Mixin for documents tab
"""
def _documents_init(self):
+ locDir = lookupDir('loc')
+ if not os.path.isdir(locDir):
+ return
+
self.tab_documents.setEnabled(True)
- locDir = lookupDir('loc')
+
parseLocDirectory(locDir)
self._documents_state = {}
Modified: pymoul/trunk/src/moul/qt/mainwindow.py
===================================================================
--- pymoul/trunk/src/moul/qt/mainwindow.py 2007-01-25 18:50:37 UTC (rev 77)
+++ pymoul/trunk/src/moul/qt/mainwindow.py 2007-01-25 18:54:52 UTC (rev 78)
@@ -68,7 +68,7 @@
self._ping_init()
self._systray_init()
self.tab_documents.setEnabled(False)
- #self._documents_init()
+ self._documents_init()
def _notimplemented(self):
"""TODO: remove me
Modified: pymoul/trunk/src/moul/qt/ui/mainwindow.py
===================================================================
--- pymoul/trunk/src/moul/qt/ui/mainwindow.py 2007-01-25 18:50:37 UTC (rev 77)
+++ pymoul/trunk/src/moul/qt/ui/mainwindow.py 2007-01-25 18:54:52 UTC (rev 78)
@@ -2,7 +2,7 @@
# Form implementation generated from reading ui file 'src\moul\qt\ui\mainwindow.ui'
#
-# Created: Thu Jan 25 19:49:10 2007
+# Created: Thu Jan 25 19:53:15 2007
# by: PyQt4 UI code generator 4.1.1
#
# WARNING! All changes made in this file will be lost!
@@ -554,10 +554,6 @@
self.groupBox_voicechat.setGeometry(QtCore.QRect(10,150,431,71))
self.groupBox_voicechat.setObjectName("groupBox_voicechat")
- self.cb_aud_voicechat = QtGui.QCheckBox(self.groupBox_voicechat)
- self.cb_aud_voicechat.setGeometry(QtCore.QRect(250,30,111,19))
- self.cb_aud_voicechat.setObjectName("cb_aud_voicechat")
-
self.verticalLayout_13 = QtGui.QWidget(self.groupBox_voicechat)
self.verticalLayout_13.setGeometry(QtCore.QRect(20,20,179,43))
self.verticalLayout_13.setObjectName("verticalLayout_13")
@@ -586,22 +582,21 @@
self.sl_aud_microphon.setTickInterval(25)
self.sl_aud_microphon.setObjectName("sl_aud_microphon")
self.vboxlayout13.addWidget(self.sl_aud_microphon)
+
+ self.cb_aud_voicechat = QtGui.QCheckBox(self.groupBox_voicechat)
+ self.cb_aud_voicechat.setGeometry(QtCore.QRect(250,30,171,19))
+ self.cb_aud_voicechat.setObjectName("cb_aud_voicechat")
self.tabwidget.addTab(self.tab_audio,"")
self.tab_time = QtGui.QWidget()
self.tab_time.setObjectName("tab_time")
- self.gb_dnitime = QtGui.QGroupBox(self.tab_time)
- self.gb_dnitime.setEnabled(True)
- self.gb_dnitime.setGeometry(QtCore.QRect(10,120,431,221))
- self.gb_dnitime.setObjectName("gb_dnitime")
-
self.gb_caverntime = QtGui.QGroupBox(self.tab_time)
self.gb_caverntime.setGeometry(QtCore.QRect(10,10,431,101))
self.gb_caverntime.setObjectName("gb_caverntime")
self.gridLayout = QtGui.QWidget(self.gb_caverntime)
- self.gridLayout.setGeometry(QtCore.QRect(10,20,381,71))
+ self.gridLayout.setGeometry(QtCore.QRect(10,20,411,71))
self.gridLayout.setObjectName("gridLayout")
self.gridlayout = QtGui.QGridLayout(self.gridLayout)
@@ -661,6 +656,11 @@
self.label_12 = QtGui.QLabel(self.gridLayout)
self.label_12.setObjectName("label_12")
self.gridlayout.addWidget(self.label_12,1,3,1,1)
+
+ self.gb_dnitime = QtGui.QGroupBox(self.tab_time)
+ self.gb_dnitime.setEnabled(False)
+ self.gb_dnitime.setGeometry(QtCore.QRect(10,120,431,221))
+ self.gb_dnitime.setObjectName("gb_dnitime")
self.tabwidget.addTab(self.tab_time,"")
self.tab_ping = QtGui.QWidget()
@@ -758,7 +758,7 @@
MainWindow.setStatusBar(self.statusbar)
self.retranslateUi(MainWindow)
- self.tabwidget.setCurrentIndex(4)
+ self.tabwidget.setCurrentIndex(0)
QtCore.QObject.connect(self.main_buttonbox,QtCore.SIGNAL("rejected()"),MainWindow.close)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
@@ -801,10 +801,9 @@
self.lb_aud_device.setText(QtGui.QApplication.translate("MainWindow", "Generic Software", None, QtGui.QApplication.UnicodeUTF8))
self.cb_aud_eax.setText(QtGui.QApplication.translate("MainWindow", "Enable EAX", None, QtGui.QApplication.UnicodeUTF8))
self.groupBox_voicechat.setTitle(QtGui.QApplication.translate("MainWindow", "Voice chat", None, QtGui.QApplication.UnicodeUTF8))
+ self.lb_aud_microphon.setText(QtGui.QApplication.translate("MainWindow", "Microphon Level", None, QtGui.QApplication.UnicodeUTF8))
self.cb_aud_voicechat.setText(QtGui.QApplication.translate("MainWindow", "Enable Voice Chat", None, QtGui.QApplication.UnicodeUTF8))
- self.lb_aud_microphon.setText(QtGui.QApplication.translate("MainWindow", "Microphon Level", None, QtGui.QApplication.UnicodeUTF8))
self.tabwidget.setTabText(self.tabwidget.indexOf(self.tab_audio), QtGui.QApplication.translate("MainWindow", "Audio", None, QtGui.QApplication.UnicodeUTF8))
- self.gb_dnitime.setTitle(QtGui.QApplication.translate("MainWindow", "D\'ni time", None, QtGui.QApplication.UnicodeUTF8))
self.gb_caverntime.setTitle(QtGui.QApplication.translate("MainWindow", "Time zones", None, QtGui.QApplication.UnicodeUTF8))
self.label_4.setText(QtGui.QApplication.translate("MainWindow", "Cavern time:", None, QtGui.QApplication.UnicodeUTF8))
self.label_5.setText(QtGui.QApplication.translate("MainWindow", "Cyan time:", None, QtGui.QApplication.UnicodeUTF8))
@@ -812,6 +811,7 @@
self.lb_cavern_utc.setText(QtGui.QApplication.translate("MainWindow", "UTC -0", None, QtGui.QApplication.UnicodeUTF8))
self.label_11.setText(QtGui.QApplication.translate("MainWindow", "(Mountain Standard Time)", None, QtGui.QApplication.UnicodeUTF8))
self.label_12.setText(QtGui.QApplication.translate("MainWindow", "(Pacific Standard Time)", None, QtGui.QApplication.UnicodeUTF8))
+ self.gb_dnitime.setTitle(QtGui.QApplication.translate("MainWindow", "D\'ni time", None, QtGui.QApplication.UnicodeUTF8))
self.tabwidget.setTabText(self.tabwidget.indexOf(self.tab_time), QtGui.QApplication.translate("MainWindow", "Time", None, QtGui.QApplication.UnicodeUTF8))
self.gb_servers.setTitle(QtGui.QApplication.translate("MainWindow", "Ping servers", None, QtGui.QApplication.UnicodeUTF8))
self.button_ping.setText(QtGui.QApplication.translate("MainWindow", "Ping", None, QtGui.QApplication.UnicodeUTF8))
Modified: pymoul/trunk/src/moul/qt/ui/mainwindow.ui
===================================================================
--- pymoul/trunk/src/moul/qt/ui/mainwindow.ui 2007-01-25 18:50:37 UTC (rev 77)
+++ pymoul/trunk/src/moul/qt/ui/mainwindow.ui 2007-01-25 18:54:52 UTC (rev 78)
@@ -147,7 +147,7 @@
<enum>QTabWidget::North</enum>
</property>
<property name="currentIndex" >
- <number>4</number>
+ <number>0</number>
</property>
<widget class="QWidget" name="tab_graphics" >
<attribute name="title" >
@@ -1173,19 +1173,6 @@
<property name="title" >
<string>Voice chat</string>
</property>
- <widget class="QCheckBox" name="cb_aud_voicechat" >
- <property name="geometry" >
- <rect>
- <x>250</x>
- <y>30</y>
- <width>111</width>
- <height>19</height>
- </rect>
- </property>
- <property name="text" >
- <string>Enable Voice Chat</string>
- </property>
- </widget>
<widget class="QWidget" name="verticalLayout_13" >
<property name="geometry" >
<rect>
@@ -1251,28 +1238,25 @@
</item>
</layout>
</widget>
+ <widget class="QCheckBox" name="cb_aud_voicechat" >
+ <property name="geometry" >
+ <rect>
+ <x>250</x>
+ <y>30</y>
+ <width>171</width>
+ <height>19</height>
+ </rect>
+ </property>
+ <property name="text" >
+ <string>Enable Voice Chat</string>
+ </property>
+ </widget>
</widget>
</widget>
<widget class="QWidget" name="tab_time" >
<attribute name="title" >
<string>Time</string>
</attribute>
- <widget class="QGroupBox" name="gb_dnitime" >
- <property name="enabled" >
- <bool>true</bool>
- </property>
- <property name="geometry" >
- <rect>
- <x>10</x>
- <y>120</y>
- <width>431</width>
- <height>221</height>
- </rect>
- </property>
- <property name="title" >
- <string>D'ni time</string>
- </property>
- </widget>
<widget class="QGroupBox" name="gb_caverntime" >
<property name="geometry" >
<rect>
@@ -1290,7 +1274,7 @@
<rect>
<x>10</x>
<y>20</y>
- <width>381</width>
+ <width>411</width>
<height>71</height>
</rect>
</property>
@@ -1397,6 +1381,22 @@
</layout>
</widget>
</widget>
+ <widget class="QGroupBox" name="gb_dnitime" >
+ <property name="enabled" >
+ <bool>false</bool>
+ </property>
+ <property name="geometry" >
+ <rect>
+ <x>10</x>
+ <y>120</y>
+ <width>431</width>
+ <height>221</height>
+ </rect>
+ </property>
+ <property name="title" >
+ <string>D'ni time</string>
+ </property>
+ </widget>
</widget>
<widget class="QWidget" name="tab_ping" >
<attribute name="title" >
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <ti...@us...> - 2007-01-25 18:50:40
|
Revision: 77
http://pymoul.svn.sourceforge.net/pymoul/?rev=77&view=rev
Author: tiran
Date: 2007-01-25 10:50:37 -0800 (Thu, 25 Jan 2007)
Log Message:
-----------
Added localization document browser
Modified Paths:
--------------
pymoul/trunk/Makefile
pymoul/trunk/src/moul/file/localization.py
pymoul/trunk/src/moul/qt/mainwindow.py
pymoul/trunk/src/moul/qt/ui/mainwindow.py
pymoul/trunk/src/moul/qt/ui/mainwindow.ui
Added Paths:
-----------
pymoul/trunk/src/moul/qt/localization.py
Modified: pymoul/trunk/Makefile
===================================================================
--- pymoul/trunk/Makefile 2007-01-25 15:25:33 UTC (rev 76)
+++ pymoul/trunk/Makefile 2007-01-25 18:50:37 UTC (rev 77)
@@ -25,7 +25,7 @@
run: compileui
PYTHONPATH="src" $(PYTHON) src/moul/qt/moulqt.py
-runexe: compileui py2exe
+exerun: compileui py2exe
dist/moulqt.exe
compileui:
Modified: pymoul/trunk/src/moul/file/localization.py
===================================================================
--- pymoul/trunk/src/moul/file/localization.py 2007-01-25 15:25:33 UTC (rev 76)
+++ pymoul/trunk/src/moul/file/localization.py 2007-01-25 18:50:37 UTC (rev 77)
@@ -33,16 +33,24 @@
from xml.sax import make_parser
from xml.sax.handler import feature_namespaces
-from moul.log import LOG
+from moul.log import getLogger
+LOG = getLogger('moul loc')
-def _add(d, key, value):
+def _addList(d, key, value):
lst = d.setdefault(key, [])
lst.append(value)
+def _addTree(d, lang, age, setname, element, key):
+ dlang = d.setdefault(lang, {})
+ dage = dlang.setdefault(age, {})
+ dset = dage.setdefault(setname, {})
+ dset[element] = key
+
class TranslationRegistry(dict):
"""Registry for Translation objects"""
- __slot__ = ('_bylanguage', '_byage', '_byset', '_byelement')
+ __slot__ = ('_bylanguage', '_byage', '_byset', '_byelement', '_tree',
+ '_ignore_age')
def __new__(cls, *args, **kwargs):
self = dict.__new__(cls, *args, **kwargs)
@@ -50,6 +58,8 @@
self._byage = {}
self._byset = {}
self._byelement = {}
+ self._tree = {}
+ self._ignore_age = [u'OptionsMenu', u'ACA', u'Global', u'KI']
return self
def register(self, translation):
@@ -59,23 +69,46 @@
(translation.fname, str(key)))
LOG.error("TranslationRegistry: %s" % msg)
raise KeyError(msg)
- _add(self._bylanguage, translation.language, key)
- _add(self._byage, translation.age, key)
- _add(self._byset, translation.set, key)
- _add(self._byelement, translation.element, key)
+ if translation.age in self._ignore_age:
+ return
+ _addList(self._bylanguage, translation.language, key)
+ _addList(self._byage, translation.age, key)
+ _addList(self._byset, translation.set, key)
+ _addList(self._byelement, translation.element, key)
+ _addTree(self._tree, translation.language, translation.age,
+ translation.set, translation.element, key)
self[key] = translation
def __setitem__(self, key, translation):
assert key == translation.key()
dict.__setitem__(self, key, translation)
+ def __repr__(self):
+ return "<%s at %s with %i elements" % (self.__class__.__name__,
+ id(self), len(self))
+
def clear(self):
dict.clear(self)
self._bylanguage.clear()
self._byage.clear()
self._byset.clear()
self._byelement.clear()
+
+ def languages(self):
+ return sorted(self._bylanguage.keys())
+ def ages(self):
+ return sorted(self._byage.keys())
+
+ def sets(self):
+ return sorted(self._byset.keys())
+
+ def elements(self):
+ return sorted(self._byelement.keys())
+
+ def tree(self):
+ return self._tree
+
translationRegistry = TranslationRegistry()
registerTranslation = translationRegistry.register
@@ -95,11 +128,12 @@
self._set = set
self._element = element
self._language = language
- LOG.debug("New translation file(%s): %s" % (fname, self.key))
+ self._fname = fname
+ #LOG.debug("New translation file(%s): %s" % (fname, self.key))
return self
def key(self):
- return (self._age, self._set, self._element, self._language)
+ return (self._language, self._age, self._set, self._element)
@property
def language(self): return self._language
@@ -113,6 +147,9 @@
@property
def element(self): return self._element
+ @property
+ def fname(self): return self._fname
+
def __str__(self):
return self.content
@@ -207,3 +244,18 @@
files.append(fname)
return {'files' : files, 'errors' : errors }
+
+def _test(path="D:/games/MystOnline/dat", out=False):
+ from pprint import pprint
+ files, errors = parseLocDirectory(path, clear=True)
+ if out:
+ print errors
+ tr = translationRegistry
+ print tr.languages()
+ print tr.ages()
+ print tr.sets()
+ print tr.elements()
+ pprint(tr.tree())
+
+if __name__ == '__main__':
+ _test(out=True)
Added: pymoul/trunk/src/moul/qt/localization.py
===================================================================
--- pymoul/trunk/src/moul/qt/localization.py (rev 0)
+++ pymoul/trunk/src/moul/qt/localization.py 2007-01-25 18:50:37 UTC (rev 77)
@@ -0,0 +1,131 @@
+# 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
+#
+"""Moul localization / documents
+"""
+__author__ = "Christian Heimes"
+__version__ = "$Id$"
+__revision__ = "$Revision$"
+
+import sys
+
+from PyQt4 import QtGui
+from PyQt4 import QtCore
+from PyQt4.QtCore import Qt
+from PyQt4.QtCore import pyqtSignature
+from PyQt4.QtCore import SIGNAL
+
+from moul.config import lookupDir
+from moul.file.localization import translationRegistry as tr
+from moul.file.localization import parseLocDirectory
+from moul.log import getLogger
+from moul.log import signalLogDecorator
+
+LOG = getLogger('moul.loc')
+
+def insertDummyQ(lst):
+ dummy = type(lst)(["<choose>"])
+ return QtCore.QStringList(dummy+lst)
+
+class LocalizationMixin(object):
+ """Mixin for documents tab
+ """
+ def _documents_init(self):
+ self.tab_documents.setEnabled(True)
+ locDir = lookupDir('loc')
+ parseLocDirectory(locDir)
+
+ self._documents_state = {}
+
+ self.connect(self.cb_doc_language, SIGNAL("currentIndexChanged(int)"),
+ self.on_cb_doc_language_currentIndexChanged)
+ self.connect(self.cb_doc_age, SIGNAL("currentIndexChanged(int)"),
+ self.on_cb_doc_age_currentIndexChanged)
+ self.connect(self.cb_doc_set, SIGNAL("currentIndexChanged(int)"),
+ self.on_cb_doc_set_currentIndexChanged)
+ #self.connect(self.cb_doc_element, SIGNAL("currentIndexChanged(int)"),
+ # self.on_cb_doc_element_currentIndexChanged)
+
+ languages = sorted(tr.languages())
+ self._documents_state['languages'] = languages
+ self.cb_doc_language.addItems(insertDummyQ(languages))
+ self.cb_doc_language.setCurrentIndex(0)
+
+ def _documents_clear(self, name):
+ names = ['language', 'age', 'set', 'element', 'doc']
+ for name in names[names.index(name):]:
+ if name == 'doc':
+ qobj = self.te_doc_view
+ else:
+ qobj = getattr(self, 'cb_doc_%s' % name)
+ qobj.clear()
+ qobj.setEnabled(False)
+
+ @pyqtSignature("int")
+ @signalLogDecorator(LOG)
+ def on_cb_doc_language_currentIndexChanged(self, idx):
+ self._documents_clear('age')
+ if idx <= 0:
+ return # <choose>
+ lang = self._documents_state['languages'][idx-1]
+ ages = sorted(tr._tree[lang].keys())
+ self._documents_state['curlanguage'] = lang
+ self._documents_state['ages'] = ages
+ self.cb_doc_age.addItems(insertDummyQ(ages))
+ self.cb_doc_age.setEnabled(True)
+
+ @pyqtSignature("int")
+ @signalLogDecorator(LOG)
+ def on_cb_doc_age_currentIndexChanged(self, idx):
+ self._documents_clear('set')
+ if idx <= 0:
+ return # <choose>
+ lang = self._documents_state['curlanguage']
+ age = self._documents_state['ages'][idx-1]
+ sets = sorted(tr._tree[lang][age].keys())
+ self._documents_state['curage'] = (lang, age)
+ self._documents_state['sets'] = sets
+ self.cb_doc_set.addItems(insertDummyQ(sets))
+ self.cb_doc_set.setEnabled(True)
+
+ @pyqtSignature("int")
+ @signalLogDecorator(LOG)
+ def on_cb_doc_set_currentIndexChanged(self, idx):
+ self._documents_clear('element')
+ if idx <= 0:
+ return # <choose>
+ lang, age = self._documents_state['curage']
+ set = self._documents_state['sets'][idx-1]
+ elements = sorted(tr._tree[lang][age][set].keys())
+ self._documents_state['curset'] = (lang, age, set)
+ self._documents_state['elements'] = elements
+ self.cb_doc_element.addItems(insertDummyQ(elements))
+ self.cb_doc_element.setEnabled(True)
+
+ @pyqtSignature("int")
+ @signalLogDecorator(LOG)
+ def on_cb_doc_element_currentIndexChanged(self, idx):
+ self._documents_clear('doc')
+ if idx <= 0:
+ return # <choose>
+ lang, age, set = self._documents_state['curset']
+ element = self._documents_state['elements'][idx-1]
+ translation = tr[(lang, age, set, element)]
+ qstr = QtCore.QString(translation)
+ self.te_doc_view.setPlainText(qstr)
+ self.te_doc_view.setEnabled(True)
+
Property changes on: pymoul/trunk/src/moul/qt/localization.py
___________________________________________________________________
Name: svn:eol-style
+ native
Modified: pymoul/trunk/src/moul/qt/mainwindow.py
===================================================================
--- pymoul/trunk/src/moul/qt/mainwindow.py 2007-01-25 15:25:33 UTC (rev 76)
+++ pymoul/trunk/src/moul/qt/mainwindow.py 2007-01-25 18:50:37 UTC (rev 77)
@@ -32,6 +32,7 @@
from PyQt4.QtCore import SIGNAL
from moul.qt.ui.mainwindow import Ui_MainWindow
+from moul.qt.localization import LocalizationMixin
from moul.config import lookupDir
from moul.file.wdysini import AudioIni
from moul.file.wdysini import GraphicsIni
@@ -44,7 +45,7 @@
LOG = getLogger('moul.qt')
-class MainWindow(QtGui.QMainWindow, Ui_MainWindow):
+class MainWindow(QtGui.QMainWindow, Ui_MainWindow, LocalizationMixin):
def __init__(self):
QtGui.QMainWindow.__init__(self)
# Set up the user interface from Designer.
@@ -66,6 +67,8 @@
self._audio_init()
self._ping_init()
self._systray_init()
+ self.tab_documents.setEnabled(False)
+ #self._documents_init()
def _notimplemented(self):
"""TODO: remove me
Modified: pymoul/trunk/src/moul/qt/ui/mainwindow.py
===================================================================
--- pymoul/trunk/src/moul/qt/ui/mainwindow.py 2007-01-25 15:25:33 UTC (rev 76)
+++ pymoul/trunk/src/moul/qt/ui/mainwindow.py 2007-01-25 18:50:37 UTC (rev 77)
@@ -2,7 +2,7 @@
# Form implementation generated from reading ui file 'src\moul\qt\ui\mainwindow.ui'
#
-# Created: Wed Jan 24 19:26:57 2007
+# Created: Thu Jan 25 19:49:10 2007
# by: PyQt4 UI code generator 4.1.1
#
# WARNING! All changes made in this file will be lost!
@@ -682,6 +682,67 @@
self.text_ping.setObjectName("text_ping")
self.tabwidget.addTab(self.tab_ping,"")
+ self.tab_documents = QtGui.QWidget()
+ self.tab_documents.setObjectName("tab_documents")
+
+ self.gb_documents = QtGui.QGroupBox(self.tab_documents)
+ self.gb_documents.setGeometry(QtCore.QRect(10,0,431,341))
+ self.gb_documents.setObjectName("gb_documents")
+
+ self.gridLayout_2 = QtGui.QWidget(self.gb_documents)
+ self.gridLayout_2.setGeometry(QtCore.QRect(10,20,411,100))
+ self.gridLayout_2.setObjectName("gridLayout_2")
+
+ self.gridlayout1 = QtGui.QGridLayout(self.gridLayout_2)
+ self.gridlayout1.setMargin(0)
+ self.gridlayout1.setSpacing(6)
+ self.gridlayout1.setObjectName("gridlayout1")
+
+ self.label_2 = QtGui.QLabel(self.gridLayout_2)
+ self.label_2.setObjectName("label_2")
+ self.gridlayout1.addWidget(self.label_2,1,0,1,1)
+
+ self.label_7 = QtGui.QLabel(self.gridLayout_2)
+ self.label_7.setObjectName("label_7")
+ self.gridlayout1.addWidget(self.label_7,3,0,1,1)
+
+ self.label = QtGui.QLabel(self.gridLayout_2)
+ self.label.setMinimumSize(QtCore.QSize(80,0))
+ self.label.setObjectName("label")
+ self.gridlayout1.addWidget(self.label,0,0,1,1)
+
+ self.label_3 = QtGui.QLabel(self.gridLayout_2)
+ self.label_3.setObjectName("label_3")
+ self.gridlayout1.addWidget(self.label_3,2,0,1,1)
+
+ self.cb_doc_language = QtGui.QComboBox(self.gridLayout_2)
+
+ sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Policy(7),QtGui.QSizePolicy.Policy(0))
+ sizePolicy.setHorizontalStretch(0)
+ sizePolicy.setVerticalStretch(0)
+ sizePolicy.setHeightForWidth(self.cb_doc_language.sizePolicy().hasHeightForWidth())
+ self.cb_doc_language.setSizePolicy(sizePolicy)
+ self.cb_doc_language.setObjectName("cb_doc_language")
+ self.gridlayout1.addWidget(self.cb_doc_language,0,1,1,1)
+
+ self.cb_doc_age = QtGui.QComboBox(self.gridLayout_2)
+ self.cb_doc_age.setObjectName("cb_doc_age")
+ self.gridlayout1.addWidget(self.cb_doc_age,1,1,1,1)
+
+ self.cb_doc_set = QtGui.QComboBox(self.gridLayout_2)
+ self.cb_doc_set.setObjectName("cb_doc_set")
+ self.gridlayout1.addWidget(self.cb_doc_set,2,1,1,1)
+
+ self.cb_doc_element = QtGui.QComboBox(self.gridLayout_2)
+ self.cb_doc_element.setObjectName("cb_doc_element")
+ self.gridlayout1.addWidget(self.cb_doc_element,3,1,1,1)
+
+ self.te_doc_view = QtGui.QTextEdit(self.gb_documents)
+ self.te_doc_view.setGeometry(QtCore.QRect(10,130,411,201))
+ self.te_doc_view.setReadOnly(True)
+ self.te_doc_view.setObjectName("te_doc_view")
+ self.tabwidget.addTab(self.tab_documents,"")
+
self.tab_about = QtGui.QWidget()
self.tab_about.setObjectName("tab_about")
@@ -697,7 +758,7 @@
MainWindow.setStatusBar(self.statusbar)
self.retranslateUi(MainWindow)
- self.tabwidget.setCurrentIndex(0)
+ self.tabwidget.setCurrentIndex(4)
QtCore.QObject.connect(self.main_buttonbox,QtCore.SIGNAL("rejected()"),MainWindow.close)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
@@ -759,6 +820,12 @@
"</style></head><body style=\" font-family:\'MS Shell Dlg 2\'; font-size:8.25pt; font-weight:400; font-style:normal; text-decoration:none;\">\n"
"<p style=\"-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;\"></p></body></html>", None, QtGui.QApplication.UnicodeUTF8))
self.tabwidget.setTabText(self.tabwidget.indexOf(self.tab_ping), QtGui.QApplication.translate("MainWindow", "Servers", None, QtGui.QApplication.UnicodeUTF8))
+ self.gb_documents.setTitle(QtGui.QApplication.translate("MainWindow", "Browse in game documents", None, QtGui.QApplication.UnicodeUTF8))
+ self.label_2.setText(QtGui.QApplication.translate("MainWindow", "Age", None, QtGui.QApplication.UnicodeUTF8))
+ self.label_7.setText(QtGui.QApplication.translate("MainWindow", "Element", None, QtGui.QApplication.UnicodeUTF8))
+ self.label.setText(QtGui.QApplication.translate("MainWindow", "Language", None, QtGui.QApplication.UnicodeUTF8))
+ self.label_3.setText(QtGui.QApplication.translate("MainWindow", "Set", None, QtGui.QApplication.UnicodeUTF8))
+ self.tabwidget.setTabText(self.tabwidget.indexOf(self.tab_documents), QtGui.QApplication.translate("MainWindow", "Documents", None, QtGui.QApplication.UnicodeUTF8))
self.label_6.setText(QtGui.QApplication.translate("MainWindow", "pyMoul tools", None, QtGui.QApplication.UnicodeUTF8))
self.tabwidget.setTabText(self.tabwidget.indexOf(self.tab_about), QtGui.QApplication.translate("MainWindow", "About", None, QtGui.QApplication.UnicodeUTF8))
Modified: pymoul/trunk/src/moul/qt/ui/mainwindow.ui
===================================================================
--- pymoul/trunk/src/moul/qt/ui/mainwindow.ui 2007-01-25 15:25:33 UTC (rev 76)
+++ pymoul/trunk/src/moul/qt/ui/mainwindow.ui 2007-01-25 18:50:37 UTC (rev 77)
@@ -147,7 +147,7 @@
<enum>QTabWidget::North</enum>
</property>
<property name="currentIndex" >
- <number>0</number>
+ <number>4</number>
</property>
<widget class="QWidget" name="tab_graphics" >
<attribute name="title" >
@@ -1454,6 +1454,110 @@
</widget>
</widget>
</widget>
+ <widget class="QWidget" name="tab_documents" >
+ <attribute name="title" >
+ <string>Documents</string>
+ </attribute>
+ <widget class="QGroupBox" name="gb_documents" >
+ <property name="geometry" >
+ <rect>
+ <x>10</x>
+ <y>0</y>
+ <width>431</width>
+ <height>341</height>
+ </rect>
+ </property>
+ <property name="title" >
+ <string>Browse in game documents</string>
+ </property>
+ <widget class="QWidget" name="gridLayout_2" >
+ <property name="geometry" >
+ <rect>
+ <x>10</x>
+ <y>20</y>
+ <width>411</width>
+ <height>100</height>
+ </rect>
+ </property>
+ <layout class="QGridLayout" >
+ <property name="margin" >
+ <number>0</number>
+ </property>
+ <property name="spacing" >
+ <number>6</number>
+ </property>
+ <item row="1" column="0" >
+ <widget class="QLabel" name="label_2" >
+ <property name="text" >
+ <string>Age</string>
+ </property>
+ </widget>
+ </item>
+ <item row="3" column="0" >
+ <widget class="QLabel" name="label_7" >
+ <property name="text" >
+ <string>Element</string>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="0" >
+ <widget class="QLabel" name="label" >
+ <property name="minimumSize" >
+ <size>
+ <width>80</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="text" >
+ <string>Language</string>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="0" >
+ <widget class="QLabel" name="label_3" >
+ <property name="text" >
+ <string>Set</string>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="1" >
+ <widget class="QComboBox" name="cb_doc_language" >
+ <property name="sizePolicy" >
+ <sizepolicy>
+ <hsizetype>7</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="1" >
+ <widget class="QComboBox" name="cb_doc_age" />
+ </item>
+ <item row="2" column="1" >
+ <widget class="QComboBox" name="cb_doc_set" />
+ </item>
+ <item row="3" column="1" >
+ <widget class="QComboBox" name="cb_doc_element" />
+ </item>
+ </layout>
+ </widget>
+ <widget class="QTextEdit" name="te_doc_view" >
+ <property name="geometry" >
+ <rect>
+ <x>10</x>
+ <y>130</y>
+ <width>411</width>
+ <height>201</height>
+ </rect>
+ </property>
+ <property name="readOnly" >
+ <bool>true</bool>
+ </property>
+ </widget>
+ </widget>
+ </widget>
<widget class="QWidget" name="tab_about" >
<attribute name="title" >
<string>About</string>
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <ti...@us...> - 2007-01-25 15:25:34
|
Revision: 76
http://pymoul.svn.sourceforge.net/pymoul/?rev=76&view=rev
Author: tiran
Date: 2007-01-25 07:25:33 -0800 (Thu, 25 Jan 2007)
Log Message:
-----------
Some logging and Makefile tweaks. Redirect stdout/stderr if sys.frozen
Modified Paths:
--------------
pymoul/trunk/Makefile
pymoul/trunk/setup_win32.py
pymoul/trunk/src/moul/log.py
Modified: pymoul/trunk/Makefile
===================================================================
--- pymoul/trunk/Makefile 2007-01-25 14:21:20 UTC (rev 75)
+++ pymoul/trunk/Makefile 2007-01-25 15:25:33 UTC (rev 76)
@@ -16,12 +16,18 @@
py2exe:
PYTHONPATH="src" $(PYTHON) setup.py $(SETUPFLAGS) py2exe
+innosetup:
+ PYTHONPATH="src" INNOSETUP="yes" $(PYTHON) setup.py $(SETUPFLAGS) py2exe
+
bdist_egg:
PYTHONPATH="src" $(PYTHON) setup.py $(SETUPFLAGS) bdist_egg
run: compileui
PYTHONPATH="src" $(PYTHON) src/moul/qt/moulqt.py
+runexe: compileui py2exe
+ dist/moulqt.exe
+
compileui:
$(PYTHON) compileui.py
@@ -39,6 +45,8 @@
exe: py2exe
+installer: innosetup
+
egg: bdist_egg
doc: doc_html
Modified: pymoul/trunk/setup_win32.py
===================================================================
--- pymoul/trunk/setup_win32.py 2007-01-25 14:21:20 UTC (rev 75)
+++ pymoul/trunk/setup_win32.py 2007-01-25 15:25:33 UTC (rev 76)
@@ -71,11 +71,15 @@
pexe['includes'] = ['sip', 'PyQt4', 'encodings', 'encodings.*']
# SSL currently not in use but imported by socket
pexe['excludes'] = ['_ssl']
+ # added by platform but not yet required
+ pexe['excludes'].extend(('win32pipe', 'win32api', 'win32con', 'win32evtlog'))
+ # added by logging.handlers.SMTPHandler but not yet required
+ pexe['excludes'].append('smtplib')
# UPX
pexe['upx'] = True
pexe['upx_args'] = '--mono --best'
# InnoSetup
- pexe['innosetup'] = True
+ pexe['innosetup'] = os.environ.get('INNOSETUP') # TODO:
pexe['app_name'] = 'pyMoul'
# not required at the moment
pexe['includes'].extend(findPyTz())
Modified: pymoul/trunk/src/moul/log.py
===================================================================
--- pymoul/trunk/src/moul/log.py 2007-01-25 14:21:20 UTC (rev 75)
+++ pymoul/trunk/src/moul/log.py 2007-01-25 15:25:33 UTC (rev 76)
@@ -37,30 +37,46 @@
# copied from moul.config to prevent circular imports
__FROZEN__ = bool(getattr(sys, 'frozen', False))
__LOG_SIGNALS__ = not __FROZEN__
-if __FROZEN__:
- level = logging.ERROR
-else:
- level = logging.DEBUG
+class LoggingStdout(object):
+ """Replacement for stdout/stderr IO
+ """
+ __slot__ = ('_logfunc',)
+
+ def __init__(self, logfunc):
+ self._logfunc = logfunc
+
+ def write(self, value):
+ while value.endswith('\n'):
+ value = value[:-1]
+ if value:
+ self._logfunc(value)
+
format = logging.Formatter('%(asctime)s %(name)-8s %(levelname)-7s %(message)s',
#'%a, %d %b %Y %H:%M:%S'
'%m-%d %H:%M:%S')
root = getLogger()
-root.setLevel(level)
+root.setLevel(logging.DEBUG)
-# Add streaming handler for sys.stderr
-shdlr = logging.StreamHandler(sys.stderr)
-shdlr.setFormatter(format)
-shdlr.setLevel(level)
-root.addHandler(shdlr)
-
# setup a memory handler to store records before we have the infrastructure
# to log events to a file
mhdlr = handlers.MemoryHandler(capacity=16*1024) # MemoryHandler doesn't flush w/o a target
mhdlr.setFormatter(format)
-mhdlr.setLevel(logging.DEBUG)
root.addHandler(mhdlr)
+if not __FROZEN__:
+ # Add streaming handler to sys.stderr.
+ # Only log to stderr when the program is not frozen!
+ shdlr = logging.StreamHandler(sys.stderr)
+ shdlr.setFormatter(format)
+ root.addHandler(shdlr)
+else:
+ # Redirect stdout and stderr to logger when running as frozen app
+ sys.stdout = LoggingStdout(getLogger('stdout').info)
+ print "Stdout redirected"
+ sys.stderr = LoggingStdout(getLogger('stderr').error)
+ print >>sys.stderr, "Stderr redirected"
+
# DEBUG system infos
LOG = getLogger('pyMoul')
LOG.debug("pyMoul version: %s" % moul_version)
@@ -77,11 +93,10 @@
LOG.debug("Adding file logger: %s" % logFile)
fhdlr = handlers.RotatingFileHandler(logFile, backupCount=9)
fhdlr.setFormatter(format)
-fhdlr.setLevel(logging.DEBUG)
root.addHandler(fhdlr)
fhdlr.doRollover()
-# flush and remove remove memory handler
+# flush and remove memory handler
mhdlr.setTarget(fhdlr)
mhdlr.flush()
root.removeHandler(mhdlr)
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <ti...@us...> - 2007-01-25 14:21:25
|
Revision: 75
http://pymoul.svn.sourceforge.net/pymoul/?rev=75&view=rev
Author: tiran
Date: 2007-01-25 06:21:20 -0800 (Thu, 25 Jan 2007)
Log Message:
-----------
More logging
Modified Paths:
--------------
pymoul/trunk/src/moul/log.py
pymoul/trunk/src/moul/osdependent/win32/__init__.py
Modified: pymoul/trunk/src/moul/log.py
===================================================================
--- pymoul/trunk/src/moul/log.py 2007-01-25 13:50:46 UTC (rev 74)
+++ pymoul/trunk/src/moul/log.py 2007-01-25 14:21:20 UTC (rev 75)
@@ -23,11 +23,12 @@
__all__ = ['LOG', 'getLogger', 'signalLogDecorator']
+import os
+import sys
+import platform
import logging
-from logging import Formatter
from logging import handlers
-import os
-import sys
+
from moul.metadata import __version__ as moul_version
# alias
@@ -41,7 +42,7 @@
else:
level = logging.DEBUG
-format = Formatter('%(asctime)s %(name)-8s %(levelname)-7s %(message)s',
+format = logging.Formatter('%(asctime)s %(name)-8s %(levelname)-7s %(message)s',
#'%a, %d %b %Y %H:%M:%S'
'%m-%d %H:%M:%S')
root = getLogger()
@@ -66,6 +67,9 @@
LOG.debug("Python: %s" % repr(sys.version_info))
LOG.debug("Python: %s" % sys.version.replace('\n', ' '))
LOG.debug("Platform: %s, OS name: %s" % (sys.platform, os.name))
+LOG.debug("system %r, node %r, release %r, version %r, machine %r, processor %r"
+ % platform.uname())
+LOG.debug("platform name: %s" % platform.platform(True))
# now get the pymoul userdata dir
from moul.config import getPyMoulDataDir
Modified: pymoul/trunk/src/moul/osdependent/win32/__init__.py
===================================================================
--- pymoul/trunk/src/moul/osdependent/win32/__init__.py 2007-01-25 13:50:46 UTC (rev 74)
+++ pymoul/trunk/src/moul/osdependent/win32/__init__.py 2007-01-25 14:21:20 UTC (rev 75)
@@ -27,7 +27,6 @@
from moul.osdependent.win32.winpath import get_homedir
from moul.osdependent.win32.winpath import get_appdata
-
MOUL_DIR = "Uru Live"
EXEC_NAME = "UruLauncher.exe"
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|