Index: /branches/numpy/anuga/utilities/log.py
===================================================================
--- /branches/numpy/anuga/utilities/log.py	(revision 7090)
+++ /branches/numpy/anuga/utilities/log.py	(revision 7091)
@@ -7,18 +7,26 @@
 Use it this way:
     import anuga.utilities.log as log
-    log.console_logging_level = log.DEBUG
+
+    # configure my logging
+    log.console_logging_level = log.INFO
+    log.log_logging_level = log.DEBUG
+    log.log_filename('./my.log')
+
+    # log away!
     log.debug('A message at DEBUG level')
     log.info('Another message, INFO level')
 
 This class uses the 'borg' pattern - there is never more than one instance
-of log data.  See
+of log data.  See the URL for the basic idea used here: modules *are*
+singletons!
+
 <http://www.suttoncourtenay.org.uk/duncan/accu/pythonpatterns.html>
-for the basic idea used here: modules *are* singletons!
 
 Until the first call to log() the user is free to play with the module data
 to configure the logging.
 
-Note that this module uses features of the logging package that were introduced
-in python2.5.  If running on earlier versions, these features are disabled:
+Note that this module uses some features of the logging package that were
+introduced in python2.5.  If running on earlier versions, the following
+features are disabled:
     . Calling module name + line number
 '''
@@ -59,7 +67,6 @@
 NOTSET = logging.NOTSET
 
-# set new_python to True if python version 2.5 or later
-(version_major, version_minor, _, _, _) = sys.version_info
-new_python = ((version_major == 2 and version_minor >= 5) or version_major > 2)
+# set _new_python to True if python version 2.5 or later
+_new_python = (sys.version_info >= 0x02050000)      # 2.5.x.x
 
 
@@ -89,5 +96,5 @@
 
         # setup the file logging system
-        if new_python:
+        if _new_python:
             fmt = '%(asctime)s %(levelname)-8s %(mname)25s:%(lnum)-4d|%(message)s'
         else:
@@ -112,5 +119,5 @@
                         logging.getLevelName(log_logging_level),
                         logging.getLevelName(console_logging_level)))
-        if new_python:
+        if _new_python:
             logging.log(logging.CRITICAL, start_msg,
                         extra={'mname': __name__, 'lnum': 0})
@@ -133,5 +140,6 @@
             break
 
-    if new_python:
+    # why are we here? ... Oh yes! Log the message!
+    if _new_python:
         logging.log(level, msg, extra={'mname': fname, 'lnum': lnum})
     else:
@@ -140,7 +148,7 @@
 ##
 # @brief Hook function to process uncaught exceptions.
-# @param type
-# @param value
-# @param traceback
+# @param type Type of exception.
+# @param value Exception data.
+# @param traceback Traceback object.
 # @note Same interface as sys.excepthook()
 def log_exception_hook(type, value, tb):
@@ -252,2 +260,4 @@
 
     test_it()
+    info('sys.version_info=%s, _new_python=%s'
+         % (str(sys.version_info), str(_new_python)))
Index: /branches/numpy/anuga/utilities/win_stuff.py
===================================================================
--- /branches/numpy/anuga/utilities/win_stuff.py	(revision 7091)
+++ /branches/numpy/anuga/utilities/win_stuff.py	(revision 7091)
@@ -0,0 +1,116 @@
+import sys
+import os
+import ctypes
+import _winreg
+
+def get_registry_value(key, subkey, value):
+    if sys.platform != 'win32':
+        raise OSError("get_registry_value is only supported on Windows")
+        
+    import _winreg
+    key = getattr(_winreg, key)
+    handle = _winreg.OpenKey(key, subkey)
+    (value, type) = _winreg.QueryValueEx(handle, value)
+    return value
+
+class SystemInformation:
+    def __init__(self):
+        self.os = self._os_version().strip()
+        self.cpu = self._cpu().strip()
+        self.browsers = self._browsers()
+        self.totalRam, self.availableRam = self._ram()
+        self.totalRam = self.totalRam / (1024*1024)
+        self.availableRam = self.availableRam / (1024*1024)
+        self.hdFree = self._disk_c() / (1024*1024*1024)
+
+    def _os_version(self):
+        def get(key):
+            return get_registry_value(
+                "HKEY_LOCAL_MACHINE", 
+                "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion",
+                key)
+        os = get("ProductName")
+        sp = get("CSDVersion")
+        build = get("CurrentBuildNumber")
+        return "%s %s (build %s)" % (os, sp, build)
+            
+    def _cpu(self):
+        return get_registry_value(
+            "HKEY_LOCAL_MACHINE", 
+            "HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0",
+            "ProcessorNameString")
+            
+    def _firefox_version(self):
+        try:
+            version = get_registry_value(
+                "HKEY_LOCAL_MACHINE", 
+                "SOFTWARE\\Mozilla\\Mozilla Firefox",
+                "CurrentVersion")
+            version = (u"Mozilla Firefox", version)
+        except WindowsError:
+            version = None
+        return version
+        
+    def _iexplore_version(self):
+        try:
+            version = get_registry_value(
+                "HKEY_LOCAL_MACHINE", 
+                "SOFTWARE\\Microsoft\\Internet Explorer",
+                "Version")
+            version = (u"Internet Explorer", version)
+        except WindowsError:
+            version = None
+        return version
+        
+    def _browsers(self):
+        browsers = []
+        firefox = self._firefox_version()
+        if firefox:
+            browsers.append(firefox)
+        iexplore = self._iexplore_version()
+        if iexplore:
+            browsers.append(iexplore)
+            
+        return browsers
+    
+    def _ram(self):
+        kernel32 = ctypes.windll.kernel32
+        c_ulong = ctypes.c_ulong
+        class MEMORYSTATUS(ctypes.Structure):
+            _fields_ = [
+                ('dwLength', c_ulong),
+                ('dwMemoryLoad', c_ulong),
+                ('dwTotalPhys', c_ulong),
+                ('dwAvailPhys', c_ulong),
+                ('dwTotalPageFile', c_ulong),
+                ('dwAvailPageFile', c_ulong),
+                ('dwTotalVirtual', c_ulong),
+                ('dwAvailVirtual', c_ulong)
+            ]
+            
+        memoryStatus = MEMORYSTATUS()
+        memoryStatus.dwLength = ctypes.sizeof(MEMORYSTATUS)
+        kernel32.GlobalMemoryStatus(ctypes.byref(memoryStatus))
+        return (memoryStatus.dwTotalPhys, memoryStatus.dwAvailPhys)
+        
+    def _disk_c(self):
+        drive = unicode(os.getenv("SystemDrive"))
+        freeuser = ctypes.c_int64()
+        total = ctypes.c_int64()
+        free = ctypes.c_int64()
+        ctypes.windll.kernel32.GetDiskFreeSpaceExW(drive, 
+                                        ctypes.byref(freeuser), 
+                                        ctypes.byref(total), 
+                                        ctypes.byref(free))
+        return freeuser.value 
+
+if __name__ == "__main__":
+    s = SystemInformation()
+    print s.os
+    print s.cpu
+    print "Browsers: "
+    print "\n".join(["   %s %s" % b for b in s.browsers])
+    print "RAM : %dMb total" % s.totalRam
+    print "RAM : %dMb free" % s.availableRam
+    print "System HD : %dGb free" % s.hdFree
+
