Author: johannes
Date: 2007-09-27 07:37:18 -0500 (Thu, 27 Sep 2007)
New Revision: 9786
Modified:
trunk/gnue-common/src/apps/GBaseApp.py
trunk/gnue-common/src/apps/GDebug.py
Log:
set log level to logging.DEBUG even if no log.conf is available. Also
honor the --debug-file option given on the commandline.
issue123 in-progress
Modified: trunk/gnue-common/src/apps/GBaseApp.py
===================================================================
--- trunk/gnue-common/src/apps/GBaseApp.py 2007-09-27 08:57:00 UTC (rev 9785)
+++ trunk/gnue-common/src/apps/GBaseApp.py 2007-09-27 12:37:18 UTC (rev 9786)
@@ -49,12 +49,12 @@
# Exceptions
# =============================================================================
-class StartupError (errors.UserError):
- """
- Error raised when a gnue application fails during initial startup prior to
- initializing to the point that better error handlers are available.
- """
- pass
+class StartupError(errors.UserError):
+ """
+ Error raised when a gnue application fails during initial startup prior to
+ initializing to the point that better error handlers are available.
+ """
+ pass
# =============================================================================
@@ -62,973 +62,990 @@
# =============================================================================
class GBaseApp:
- """
- The base class of the various GNUe application classes.
+ """
+ The base class of the various GNUe application classes.
- GBaseApp Provides the following features
- - Command line argument parsing
- - Run time debug output levels
- - An integrated profiler
- - An integrated debugger
- """
+ GBaseApp Provides the following features
+ - Command line argument parsing
+ - Run time debug output levels
+ - An integrated profiler
+ - An integrated debugger
+ """
- # Attributes to be overwritten by subclasses
- VERSION = "0.0.0"
- NAME = "GNUe Application"
- COMMAND_OPTIONS = [] # Should be in same format as _base_options below
- SUMMARY = "A brief summary of the program goes here."
- COMMAND = "app"
- USAGE = "[options]"
- USE_CONNECTIONS = 1 # Set to 1 if the program uses dbdrivers
- USE_DATABASE_OPTIONS = 0 # Also implies USE_CONNECTIONS = 1
- USE_RPC_OPTIONS = 0
+ # Attributes to be overwritten by subclasses
+ VERSION = "0.0.0"
+ NAME = "GNUe Application"
+ COMMAND_OPTIONS = [] # Should be in same format as _base_options below
+ SUMMARY = "A brief summary of the program goes here."
+ COMMAND = "app"
+ USAGE = "[options]"
+ USE_CONNECTIONS = 1 # Set to 1 if the program uses dbdrivers
+ USE_DATABASE_OPTIONS = 0 # Also implies USE_CONNECTIONS = 1
+ USE_RPC_OPTIONS = 0
- # More options, but won't be changed unless this is a non-GNUe app using
- # GNUe-Common
- AUTHOR = "GNU Enterprise Project"
- EMAIL = "[email protected]"
- REPORT_BUGS_TO = "Please report any bugs to [email protected]."
- CONFIGFILE = "gnue.conf"
+ # More options, but won't be changed unless this is a non-GNUe app using
+ # GNUe-Common
+ AUTHOR = "GNU Enterprise Project"
+ EMAIL = "[email protected]"
+ REPORT_BUGS_TO = "Please report any bugs to [email protected]."
+ CONFIGFILE = "gnue.conf"
- # Attributes that will be set by GClientApp after __init__ has run
- OPTIONS = {} # Will contain a hash containing command line options
- ARGUMENTS = [] # Will contain an array of command line arguments
- connections = None # Will contain a GConnection object
+ # Attributes that will be set by GClientApp after __init__ has run
+ OPTIONS = {} # Will contain a hash containing command line options
+ ARGUMENTS = [] # Will contain an array of command line arguments
+ connections = None # Will contain a GConnection object
- # ---------------------------------------------------------------------------
- # Create a new GNUe Application
- # ---------------------------------------------------------------------------
+ # -------------------------------------------------------------------------
+ # Create a new GNUe Application
+ # -------------------------------------------------------------------------
- def __init__ (self, connections = None, application = 'common',
- defaults = None):
- """
- @param connections:
- @param application:
- @param defaults:
- """
+ def __init__(self, connections=None, application='common', defaults=None):
+ """
+ @param connections:
+ @param application:
+ @param defaults:
+ """
- self.configDefaults = defaults
-
- sys.excepthook = self.excepthook
+ self.configDefaults = defaults
- # Basic options
- self._base_options = [
- ##
- ## Base options
- ##
- CommandOption ('version', category = "base", action = self.doVersion,
- help = u_('Displays the version information for this program.')),
+ sys.excepthook = self.excepthook
- CommandOption ('debug-level', category = "base", default = 0,
- argument = u_("level"),
- help = u_('Enables debugging messages. Argument specifies the '
- 'level of messages to display (e.g., "--debug-level 5" '
- 'displays all debugging messages at level 5 or below.)')),
+ # Basic options
+ self._base_options = [
+ ##
+ ## Base options
+ ##
+ CommandOption('version', category="base", action=self.doVersion,
+ help=u_('Displays the version information for this program.')),
- CommandOption ('debug-file', category = "base", argument = u_("filename"),
- help = u_('Sends all debugging messages to a specified file '
- '(e.g., "--debug-file trace.log" sends all output to '
- '"trace.log")')),
-
- # This is actually handled during the initial GDebug import but is added
- # here so that applications won't abort with an unknown option.
- CommandOption ('debug-imports', category = "dev",
- help = u_('All python imports are logged to stdout')),
+ CommandOption('debug-level', category="base", default=0,
+ argument=u_("level"),
+ help=u_('Enables debugging messages. Argument specifies the '
+ 'level of messages to display (e.g., "--debug-level 5" '
+ 'displays all debugging messages at level 5 or below.)')),
- CommandOption ('silent', category = "base",
- help = u_('Displays no output at all.')),
+ CommandOption('debug-file', category="base", argument=u_("filename"),
+ help = u_('Sends all debugging messages to a specified file '
+ '(e.g., "--debug-file trace.log" sends all output to '
+ '"trace.log")')),
- CommandOption ('help', category = "base", action = self.printHelp,
- help = u_('Displays this help screen.')),
+ # This is actually handled during the initial GDebug import but is
+ # added here so that applications won't abort with an unknown
+ # option.
+ CommandOption('debug-imports', category="dev",
+ help=u_('All python imports are logged to stdout')),
- CommandOption ('help-config', category = "base",
- action = self.doHelpConfig,
- help = u_('Displays a list of valid configuration file entries, their '
- 'purpose, and their default values.')),
+ CommandOption('silent', category="base",
+ help=u_('Displays no output at all.')),
- ##
- ## Developer options
- ##
+ CommandOption('help', category="base", action=self.printHelp,
+ help=u_('Displays this help screen.')),
- CommandOption ('help-dev', category = "base", action = self.printHelpDev,
- help = u_('Display all options of interest to core developers. ')),
+ CommandOption('help-config', category="base",
+ action=self.doHelpConfig,
+ help=u_('Displays a list of valid configuration file entries, '
+ 'their purpose, and their default values.')),
- CommandOption ('selfdoc', category = "dev", action = self.doSelfDoc,
- argument = u_("type[,subtype]"),
- help = u_('Generates self-documentation.')),
+ ##
+ ## Developer options
+ ##
- CommandOption ('selfdoc-format', category = "dev",
- argument = u_("format"),
- help = u_('Format to output the self-documentation in. Supported '
- 'formats are dependent on the type of selfdoc being '
- 'created.')),
+ CommandOption('help-dev', category="base", action=self.printHelpDev,
+ help=u_('Display all options of interest to core developers. ')),
- CommandOption ('selfdoc-file', category = "dev",
- argument = u_("filename"),
- help = u_('Specifies the filename that selfdoc should write to. If not '
- 'provided, output is sent to stdout.')),
+ CommandOption('selfdoc', category="dev", action=self.doSelfDoc,
+ argument=u_("type[,subtype]"),
+ help=u_('Generates self-documentation.')),
- CommandOption ('selfdoc-options', category = "dev",
- argument = u_("options"),
- help = u_('Options specific to individual selfdoc types.')),
+ CommandOption('selfdoc-format', category="dev",
+ argument=u_("format"),
+ help=u_('Format to output the self-documentation in. Supported '
+ 'formats are dependent on the type of selfdoc being '
+ 'created.')),
- CommandOption ('profile', category = "dev",
- help = u_("Run Python's built-in profiler and display the resulting "
- "run statistics.")),
+ CommandOption('selfdoc-file', category="dev",
+ argument=u_("filename"),
+ help=u_('Specifies the filename that selfdoc should write to. If '
+ 'not provided, output is sent to stdout.')),
- CommandOption ('interactive-debugger', category = "dev",
- help = u_("Run the app inside Python's built-in debugger ")),
+ CommandOption('selfdoc-options', category="dev",
+ argument=u_("options"),
+ help=u_('Options specific to individual selfdoc types.')),
- CommandOption ('debug-gc', 'g', 'debug-gc', True, None, "logfile",
- category = "dev", action = self.__installGCHandler,
- help = u_("Debug Python's garbage collection on a SIGUSR1. If the "
- "argument is empty 'garbage.log' will be used as "
- "logfile.")),
+ CommandOption('profile', category="dev",
+ help=u_("Run Python's built-in profiler and display the resulting "
+ "run statistics.")),
- #CommandOption ('garbagelog', 'l'
- ]
+ CommandOption('interactive-debugger', category="dev",
+ help=u_("Run the app inside Python's built-in debugger ")),
- if self.USE_DATABASE_OPTIONS:
- self.USE_CONNECTIONS = 1
- self._base_options.extend ([ \
- CommandOption ('username', category = "connections", default = '',
- argument = u_('name'),
- help = u_('Username used to log into the database. Note that if '
- 'specified, this will be used for all databases. If not '
- 'supplied, the program will prompt for username.')),
+ CommandOption('debug-gc', 'g', 'debug-gc', True, None, "logfile",
+ category="dev", action=self.__installGCHandler,
+ help=u_("Debug Python's garbage collection on a SIGUSR1. If the "
+ "argument is empty 'garbage.log' will be used as "
+ "logfile.")),
+ ]
- CommandOption ('password', category = "connections", default = '',
- argument = u_('passwd'),
- help = u_('Password used to log into the database. Note that if '
- 'specified, this will be used for all databases. If not '
- 'supplied, the program will prompt for password if needed.'
- '\nNOTE: SUPPLYING A PASSWORD VIA THE COMMAND LINE MAY BE '
- 'CONSIDERED A SECURITY RISK AND IS NOT RECOMMENDED.'))])
+ if self.USE_DATABASE_OPTIONS:
+ self.USE_CONNECTIONS = 1
+ self._base_options.extend([ \
+ CommandOption('username', category="connections", default='',
+ argument=u_('name'),
+ help=u_('Username used to log into the database. Note that if '
+ 'specified, this will be used for all databases. If '
+ 'not supplied, the program will prompt for username.')),
- if self.USE_CONNECTIONS:
- self._base_options += [
- CommandOption ('help-connections', category = "base",
- action = self.printHelpConn,
- help = u_('Display help information related to database '
- 'connections, including a list of available drivers.')),
+ CommandOption('password', category="connections", default='',
+ argument=u_('passwd'),
+ help=u_('Password used to log into the database. Note that '
+ 'if specified, this will be used for all databases. '
+ 'If not supplied, the program will prompt for '
+ 'password if needed.\nNOTE: SUPPLYING A PASSWORD VIA '
+ 'THE COMMAND LINE MAY BE CONSIDERED A SECURITY RISK '
+ 'AND IS NOT RECOMMENDED.'))])
- CommandOption ('connections', category = "connections",
- argument = u_("location"),
- help = u_('Specifies the location of the connection definition file. '
- '<location> may specify a file name '
- '(/usr/local/gnue/etc/connections.conf),'
- 'or a URL location '
- '(http://localhost/connections.conf).'
- 'If this option is not specified, the environent variable '
- 'GNUE_CONNECTIONS is checked.'
- 'If neither of them is set, "%s" is used as a default.') %
- os.path.join (paths.config, "connections.conf")) ]
+ if self.USE_CONNECTIONS:
+ self._base_options += [
+ CommandOption('help-connections', category="base",
+ action=self.printHelpConn,
+ help=u_('Display help information related to database '
+ 'connections, including a list of available drivers.')),
- # Python version check
- if not hasattr (sys, 'hexversion') or sys.hexversion < 0x02030000:
- msg = u_("This application requires Python 2.3 or greater.")
- if hasattr (sys, 'version'):
- msg = u_("This application requires Python 2.3 or greater. "
- "You are running Python %s") % sys.version [:5]
+ CommandOption('connections', category="connections",
+ argument=u_("location"),
+ help=u_('Specifies the location of the connection definition '
+ 'file. <location> may specify a file name '
+ '(/usr/local/gnue/etc/connections.conf),'
+ 'or a URL location '
+ '(http://localhost/connections.conf).'
+ 'If this option is not specified, the environent '
+ 'variable GNUE_CONNECTIONS is checked.'
+ 'If neither of them is set, "%s" is used as a '
+ 'default.') %
+ os.path.join(paths.config, "connections.conf")) ]
- raise errors.AdminError, msg
+ # Python version check
+ if not hasattr(sys, 'hexversion') or sys.hexversion < 0x02030000:
+ msg = u_("This application requires Python 2.3 or greater.")
+ if hasattr(sys, 'version'):
+ msg = u_("This application requires Python 2.3 or greater. "
+ "You are running Python %s") % sys.version[:5]
+ raise errors.AdminError, msg
- #
- # Get all command line options and arguments
- #
- shortoptions = ""
- longoptions = []
- lookup = {}
- actions = {}
- # Convert old-style options to new-style
- if self.COMMAND_OPTIONS and \
- isinstance (self.COMMAND_OPTIONS [0], types.ListType):
- options = self.COMMAND_OPTIONS
- self.COMMAND_OPTIONS = []
- for option in options:
- self.COMMAND_OPTIONS.append (CommandOption (*option))
+ #
+ # Get all command line options and arguments
+ #
+ shortoptions = ""
+ longoptions = []
+ lookup = {}
+ actions = {}
- for optionset in [self._base_options, self.COMMAND_OPTIONS]:
- for option in optionset:
- self.OPTIONS[option.name] = option.default
- if option.shortOption:
- shortoptions += option.shortOption
- lookup["-" + option.shortOption] = option.name
- lookup["--" + option.longOption] = option.name
- if option.action:
- actions["--" + option.longOption] = option.action
- lo = option.longOption
- if option.acceptsArgument:
- lo += '='
- shortoptions += ':'
- longoptions.append(lo)
+ # Convert old-style options to new-style
+ if self.COMMAND_OPTIONS and \
+ isinstance(self.COMMAND_OPTIONS[0], types.ListType):
+ options = self.COMMAND_OPTIONS
+ self.COMMAND_OPTIONS = []
+ for option in options:
+ self.COMMAND_OPTIONS.append(CommandOption(*option))
+ for optionset in [self._base_options, self.COMMAND_OPTIONS]:
+ for option in optionset:
+ self.OPTIONS[option.name] = option.default
+ if option.shortOption:
+ shortoptions += option.shortOption
+ lookup["-" + option.shortOption] = option.name
+ lookup["--" + option.longOption] = option.name
+ if option.action:
+ actions["--" + option.longOption] = option.action
+ lo = option.longOption
+ if option.acceptsArgument:
+ lo += '='
+ shortoptions += ':'
+ longoptions.append(lo)
- # mod_python apps don't have an argv
- # so create an empty one.
- # TODO: This class needs adjusted to
- # be more efficent in mod_python cases
- # But not this close to a release :)
- if not sys.__dict__.has_key('argv'):
- sys.argv = []
- try:
- opt, self.ARGUMENTS = getopt.getopt (sys.argv[1:], shortoptions,
- longoptions)
- except getopt.error, msg:
- raise StartupError, "%s" % msg
+ # mod_python apps don't have an argv
+ # so create an empty one.
+ # TODO: This class needs adjusted to
+ # be more efficent in mod_python cases
+ # But not this close to a release :)
+ if not sys.__dict__.has_key('argv'):
+ sys.argv = []
- pendingActions = []
- for o in opt:
- if len(o[1]):
- self.OPTIONS[lookup[o[0]]] = o[1]
- else:
- self.OPTIONS[lookup[o[0]]] = True
+ try:
+ opt, self.ARGUMENTS = getopt.getopt(sys.argv[1:], shortoptions,
+ longoptions)
+ except getopt.error, msg:
+ raise StartupError, "%s" % msg
- # Add any actions to our list
- try:
- pendingActions.append(actions[o[0]])
- except KeyError:
- pass
+ pendingActions = []
+ for o in opt:
+ if len(o[1]):
+ self.OPTIONS[lookup[o[0]]] = o[1]
+ else:
+ self.OPTIONS[lookup[o[0]]] = True
- for task in pendingActions:
- task()
+ # Add any actions to our list
+ try:
+ pendingActions.append(actions[o[0]])
+ except KeyError:
+ pass
- self._run = self.run
+ for task in pendingActions:
+ task()
- # Are we silent?
- if self.OPTIONS['silent']:
- # our file objects (/dev/null and nul) has no encoding, unlike stdout...
- import __builtin__
- __builtin__.__dict__['u_'] = __builtin__.__dict__['_']
- if os.name == 'posix':
- sout = open('/dev/null','w')
- serr = open('/dev/null','w')
- elif os.name == 'nt':
- sout = open('nul', 'w')
- serr = open('nul', 'w')
+ self._run = self.run
- try:
- os.close(sys.stdout.fileno())
- sys.stdout = sout
- os.close(sys.stderr.fileno())
- sys.stderr = serr
+ # Are we silent?
+ if self.OPTIONS['silent']:
+ # our file objects (/dev/null and nul) has no encoding, unlike
+ # stdout...
+ import __builtin__
+ __builtin__.__dict__['u_'] = __builtin__.__dict__['_']
+ if os.name == 'posix':
+ sout = open('/dev/null','w')
+ serr = open('/dev/null','w')
+ elif os.name == 'nt':
+ sout = open('nul', 'w')
+ serr = open('nul', 'w')
- except:
- pass
+ try:
+ os.close(sys.stdout.fileno())
+ sys.stdout = sout
+ os.close(sys.stderr.fileno())
+ sys.stderr = serr
- # Should we profile?
- if self.OPTIONS['profile']:
- self.run = self._profile
+ except:
+ pass
- # Setup debugging
- # Should we run in debugger?
- elif self.OPTIONS['interactive-debugger']:
- self.run = self._debugger
+ # Should we profile?
+ if self.OPTIONS['profile']:
+ self.run = self._profile
- try:
- GDebug.setDebug ("%s" % self.OPTIONS ['debug-level'],
- self.OPTIONS ['debug-file'])
- except ValueError:
- raise StartupError, \
- u_('The debug_level option ("-d") expects numerical values.')
+ # Setup debugging
+ # Should we run in debugger?
+ elif self.OPTIONS['interactive-debugger']:
+ self.run = self._debugger
- assert gDebug (2, "Python %s" % sys.version)
- assert gDebug (2, "Run Options: %s" % opt)
- assert gDebug (2, "Run Arguments: %s" % self.ARGUMENTS)
+ try:
+ GDebug.setDebug("%s" % self.OPTIONS['debug-level'],
+ self.OPTIONS['debug-file'])
+ except ValueError:
+ raise StartupError, \
+ u_('The debug_level option ("-d") expects numerical values.')
- # Read the config files
- if application:
- try:
- self.configurationManager = GConfig.GConfig (application,
- self.configDefaults, configFilename = self.CONFIGFILE)
+ assert gDebug(2, "Python %s" % sys.version)
+ assert gDebug(2, "Run Options: %s" % opt)
+ assert gDebug(2, "Run Arguments: %s" % self.ARGUMENTS)
- except ConfigParser.NoSectionError, msg:
- raise errors.AdminError, \
- u_("The gnue.conf file is incomplete:\n %s") % msg
+ # Read the config files
+ if application:
+ try:
+ self.configurationManager = GConfig.GConfig(application,
+ self.configDefaults,
+ configFilename=self.CONFIGFILE)
- # Add custom import to python's namespace
- try:
- extrapaths = gConfig('ImportPath')
- except:
- extrapaths = ""
- if extrapaths:
- for path in extrapaths.split(','):
- p = path.strip()
- if not p in sys.path:
- sys.path.append(p)
+ except ConfigParser.NoSectionError, msg:
+ raise errors.AdminError, \
+ u_("The gnue.conf file is incomplete:\n %s") % msg
- # Get the connection definitions
- if connections != None:
- assert gDebug(7,"Reusing connections instance")
- self.connections = connections
- elif self.USE_CONNECTIONS:
+ # Add custom import to python's namespace
+ try:
+ extrapaths = gConfig('ImportPath')
+ except:
+ extrapaths = ""
- # Check for default username/password
- lhOptions = {}
- if self.USE_DATABASE_OPTIONS:
- if self.OPTIONS['username']:
- lhOptions['_username'] = self.OPTIONS['username']
- if self.OPTIONS['password']:
- lhOptions['_password'] = self.OPTIONS['password']
+ if extrapaths:
+ for path in extrapaths.split(','):
+ p = path.strip()
+ if not p in sys.path:
+ sys.path.append(p)
- if self.OPTIONS['connections']:
- self.connections_file = self.OPTIONS['connections']
- elif os.environ.has_key('GNUE_CONNECTIONS'):
- self.connections_file = os.environ['GNUE_CONNECTIONS']
- else:
- self.connections_file = os.path.join (paths.config, "connections.conf")
+ # Get the connection definitions
+ if connections != None:
+ assert gDebug(7,"Reusing connections instance")
+ self.connections = connections
+ elif self.USE_CONNECTIONS:
- assert gDebug(2, 'Connection Definition: "%s"' % self.connections_file)
+ # Check for default username/password
+ lhOptions = {}
+ if self.USE_DATABASE_OPTIONS:
+ if self.OPTIONS['username']:
+ lhOptions['_username'] = self.OPTIONS['username']
+ if self.OPTIONS['password']:
+ lhOptions['_password'] = self.OPTIONS['password']
- try:
- self.connections = GConnections.GConnections (self.connections_file,
- loginOptions = lhOptions)
- except GConnections.InvalidFormatError, msg:
- raise errors.AdminError, \
- u_("Unable to load the connections definition file.\n\n"
- "The connections file is in an invalid format.\n%s") % msg
+ if self.OPTIONS['connections']:
+ self.connections_file = self.OPTIONS['connections']
+ elif os.environ.has_key('GNUE_CONNECTIONS'):
+ self.connections_file = os.environ['GNUE_CONNECTIONS']
+ else:
+ self.connections_file = os.path.join(paths.config,
+ "connections.conf")
- except IOError:
- raise StartupError, \
- u_("Unable to load the connections definition file: %s.") \
- % self.connections_file
+ assert gDebug(2, 'Connection Definition: "%s"' %
+ self.connections_file)
+ try:
+ self.connections = GConnections.GConnections( \
+ self.connections_file, loginOptions = lhOptions)
- # ---------------------------------------------------------------------------
- # Run the program
- # ---------------------------------------------------------------------------
+ except GConnections.InvalidFormatError, msg:
+ raise errors.AdminError, \
+ u_("Unable to load the connections definition file.\n\n"
+ "The connections file is in an invalid format.\n%s") \
+ % msg
- def run(self):
- """
- Run the program. This function will be overriden by a descendant.
- """
+ except IOError:
+ raise StartupError, \
+ u_("Unable to load the connections definition file: %s.") \
+ % self.connections_file
- pass
+ # -------------------------------------------------------------------------
+ # Run the program
+ # -------------------------------------------------------------------------
- # ---------------------------------------------------------------------------
- # Add a new option to the program
- # ---------------------------------------------------------------------------
+ def run(self):
+ """
+ Run the program. This function will be overriden by a descendant.
+ """
- def addCommandOption(self, *args, **parms):
- """
- Create a new command option and add it to the options sequence.
+ pass
- @param args: positional arguments for the command option's constructor
- @param parms: keyword arguments for the command option's constructor
- """
- self.COMMAND_OPTIONS.append (CommandOption (*args, **parms))
+ # -------------------------------------------------------------------------
+ # Add a new option to the program
+ # -------------------------------------------------------------------------
+ def addCommandOption(self, *args, **parms):
+ """
+ Create a new command option and add it to the options sequence.
- # ---------------------------------------------------------------------------
- # Display version information for this application
- # ---------------------------------------------------------------------------
+ @param args: positional arguments for the command option's constructor
+ @param parms: keyword arguments for the command option's constructor
+ """
- def printVersion (self):
- """
- Display version information for this application
- """
+ self.COMMAND_OPTIONS.append(CommandOption(*args, **parms))
- from gnue.common import VERSION as commonVersion
- print o(u_("\n%(name)s\nVersion %(version)s\n") \
- % {'name': self.NAME, 'version': self.VERSION})
- print o(u_("GNUe Common Version %s\n") % commonVersion)
+ # -------------------------------------------------------------------------
+ # Display version information for this application
+ # -------------------------------------------------------------------------
- # ---------------------------------------------------------------------------
- # Build help options
- # ---------------------------------------------------------------------------
+ def printVersion(self):
+ """
+ Display version information for this application
+ """
- def buildHelpOptions (self, category = None):
- """
- Build 'help text' for all options of the given category. If no category is
- given all options except the 'dev' options will be included.
+ from gnue.common import VERSION as commonVersion
+ print o(u_("\n%(name)s\nVersion %(version)s\n") \
+ % {'name': self.NAME, 'version': self.VERSION})
+ print o(u_("GNUe Common Version %s\n") % commonVersion)
- @param category: if not None only options of this category will be included.
- @return: string with the help text for all matching options.
- """
+ # -------------------------------------------------------------------------
+ # Build help options
+ # -------------------------------------------------------------------------
- allOptions = {}
- descriptors = {}
- maxLength = 0
+ def buildHelpOptions(self, category=None):
+ """
+ Build 'help text' for all options of the given category. If no category
+ is given all options except the 'dev' options will be included.
- for optionset in [self._base_options, self.COMMAND_OPTIONS]:
- for option in optionset:
- # Limit this to the correct category. A category of None implies all
- # options except "dev".
- if not ( ( category is None and \
- option.category != "dev" ) or \
- ( category == option.category ) ):
- continue
+ @param category: if not None only options of this category will be
+ included.
- allOptions [option.longOption.upper ()] = option
+ @return: string with the help text for all matching options.
+ """
- if option.acceptsArgument:
- descr = '--%s <%s>' % (option.longOption, option.argumentName)
- else:
- descr = '--%s' % (option.longOption)
- if option.shortOption:
- descr += ', -%s' % option.shortOption
+ allOptions = {}
+ descriptors = {}
+ maxLength = 0
- descriptors [option.longOption.upper()] = descr
+ for optionset in [self._base_options, self.COMMAND_OPTIONS]:
+ for option in optionset:
+ # Limit this to the correct category. A category of None
+ # implies all options except "dev".
+ if not ((category is None and \
+ option.category != "dev") or \
+ (category == option.category)):
+ continue
- maxLength = max(len (descr), maxLength)
+ allOptions[option.longOption.upper()] = option
- maxLength = min(10, maxLength)
+ if option.acceptsArgument:
+ descr = '--%s <%s>' % (option.longOption,
+ option.argumentName)
+ else:
+ descr = '--%s' % (option.longOption)
+ if option.shortOption:
+ descr += ', -%s' % option.shortOption
- sorted = allOptions.keys ()
- sorted.sort ()
+ descriptors[option.longOption.upper()] = descr
- dispOptions = u""
+ maxLength = max(len(descr), maxLength)
- for optionKey in sorted:
- margin = maxLength + 4
- width = 78 - margin
- pos = 0
+ maxLength = min(10, maxLength)
- if len (descriptors [optionKey]) > maxLength:
- dispOptions += "\n %s\n%s" % (descriptors [optionKey], " " * margin)
- else:
- dispOptions += "\n %s %s" % (descriptors [optionKey],
- " " * (maxLength - len (descriptors [optionKey])))
+ sorted = allOptions.keys()
+ sorted.sort()
- for word in allOptions [optionKey].help.split():
- if (len (word) + pos) > width:
- pos = 0
- dispOptions += "\n" + " " * margin
+ dispOptions = u""
- pos = pos + len (word) + 1
+ for optionKey in sorted:
+ margin = maxLength + 4
+ width = 78 - margin
+ pos = 0
- dispOptions += word + " "
+ if len(descriptors[optionKey]) > maxLength:
+ dispOptions += "\n %s\n%s" % (descriptors[optionKey],
+ " " * margin)
+ else:
+ dispOptions += "\n %s %s" % (descriptors[optionKey],
+ " " * (maxLength - len(descriptors[optionKey])))
- dispOptions += "\n"
+ for word in allOptions[optionKey].help.split():
+ if (len(word) + pos) > width:
+ pos = 0
+ dispOptions += "\n" + " " * margin
- return dispOptions
+ pos = pos + len(word) + 1
+ dispOptions += word + " "
- # ---------------------------------------------------------------------------
- # Print a usage header
- # ---------------------------------------------------------------------------
+ dispOptions += "\n"
- def printHelpHeader(self):
- """
- Print version information and the usage header
- """
+ return dispOptions
- self.printVersion ()
- print o(u_("Usage: ") + self.COMMAND + ' ' + self.USAGE)
- print
+ # -------------------------------------------------------------------------
+ # Print a usage header
+ # -------------------------------------------------------------------------
- # ---------------------------------------------------------------------------
- # Print help footer
- # ---------------------------------------------------------------------------
+ def printHelpHeader(self):
+ """
+ Print version information and the usage header
+ """
- def printHelpFooter(self):
- """
- Print the help footer including the address for bug reports.
- """
+ self.printVersion()
+ print o(u_("Usage: ") + self.COMMAND + ' ' + self.USAGE)
+ print
- print
- print o("%s\n" % self.REPORT_BUGS_TO)
+ # -------------------------------------------------------------------------
+ # Print help footer
+ # -------------------------------------------------------------------------
- # ---------------------------------------------------------------------------
- # Display help information for this program
- # ---------------------------------------------------------------------------
+ def printHelpFooter(self):
+ """
+ Print the help footer including the address for bug reports.
+ """
- def printHelp (self):
- """
- Print help information for this application and quit the program. This
- includes the version, the usage, the application's summary and all
- available command options (without the 'developer' options).
- """
+ print
+ print o("%s\n" % self.REPORT_BUGS_TO)
- self.printHelpHeader ()
- print o("\n" + self.SUMMARY + '\n')
- print o(u_('Available command line options:'))
- print o(self.buildHelpOptions ())
- self.printHelpFooter ()
+ # -------------------------------------------------------------------------
+ # Display help information for this program
+ # -------------------------------------------------------------------------
- sys.exit ()
+ def printHelp(self):
+ """
+ Print help information for this application and quit the program. This
+ includes the version, the usage, the application's summary and all
+ available command options (without the 'developer' options).
+ """
+ self.printHelpHeader()
+ print o("\n" + self.SUMMARY + '\n')
- # ---------------------------------------------------------------------------
- # Display dev help information for this program
- # ---------------------------------------------------------------------------
+ print o(u_('Available command line options:'))
+ print o(self.buildHelpOptions())
+ self.printHelpFooter()
- def printHelpDev (self):
- """
- Print help information for this application and quit the program. This
- includes the version, usage and all available developer's command options.
- """
+ sys.exit()
- self.printHelpHeader ()
- print o(u_("The following options are mainly of interest to GNUe "
- "developers."))
- print o(u_("To view general help, run this command with the --help "
- "option."))
- print
- print o(u_('Developer-specific command line options:'))
- print o(self.buildHelpOptions ("dev"))
- self.printHelpFooter ()
+ # -------------------------------------------------------------------------
+ # Display dev help information for this program
+ # -------------------------------------------------------------------------
- sys.exit ()
+ def printHelpDev(self):
+ """
+ Print help information for this application and quit the program. This
+ includes the version, usage and all available developer's command
+ options.
+ """
+ self.printHelpHeader()
- # ---------------------------------------------------------------------------
- # Print connection-specific help information
- # ---------------------------------------------------------------------------
+ print o(u_("The following options are mainly of interest to GNUe "
+ "developers."))
+ print o(u_("To view general help, run this command with the --help "
+ "option."))
+ print
+ print o(u_('Developer-specific command line options:'))
+ print o(self.buildHelpOptions("dev"))
+ self.printHelpFooter()
- def printHelpConn (self):
- """
- Print connection/database-related help information and quit the program.
- """
+ sys.exit()
- self.printHelpHeader ()
- print o(u_("The following connection/database-related options are "
- "available."))
- print o(u_("To view general help, run this command with the --help "
- "option."))
- print
- print o(u_('Database/connection command line options:'))
- print o(self.buildHelpOptions ("connections"))
- print
- print o(u_('The following database drivers are installed on your system:'))
- print " TODO\n"
- # print self.connections.getAvailableDrivers()
- self.printHelpFooter ()
+ # -------------------------------------------------------------------------
+ # Print connection-specific help information
+ # -------------------------------------------------------------------------
- sys.exit ()
+ def printHelpConn(self):
+ """
+ Print connection/database-related help information and quit the program.
+ """
+ self.printHelpHeader()
- # ---------------------------------------------------------------------------
- # Run the self-documentation for a program
- # ---------------------------------------------------------------------------
+ print o(u_("The following connection/database-related options are "
+ "available."))
+ print o(u_("To view general help, run this command with the --help "
+ "option."))
+ print
+ print o(u_('Database/connection command line options:'))
+ print o(self.buildHelpOptions("connections"))
+ print
+ print o(u_('The following database drivers are installed on ' \
+ 'your system:'))
+ print " TODO\n"
+ # print self.connections.getAvailableDrivers()
+ self.printHelpFooter()
- def selfdoc (self, command, handle, format = None, options = {}):
- """
- Run the self-documentation for an application. Currently only the command
- 'manpage' is supported.
+ sys.exit()
- @param command: can be 'manpage' only atm
- @param handle: file-like object to write the documentation contents to.
- This file handle must be already opened for writing.
- @param format: not used in the current version
- @param options: not used in the current version
- """
- if command == 'manpage':
- import manpage
- manpage.ManPage (self, handle, format, options)
+ # -------------------------------------------------------------------------
+ # Run the self-documentation for a program
+ # -------------------------------------------------------------------------
+ def selfdoc(self, command, handle, format = None, options = {}):
+ """
+ Run the self-documentation for an application. Currently only the
+ command 'manpage' is supported.
- # ---------------------------------------------------------------------------
- #
- # ---------------------------------------------------------------------------
+ @param command: can be 'manpage' only atm
+ @param handle: file-like object to write the documentation contents to.
+ This file handle must be already opened for writing.
+ @param format: not used in the current version
+ @param options: not used in the current version
+ """
- def getCommandLineParameters (self, paramList):
- """
- Convert a sequence of parameters (i.e. '--foo=bar') into a parameter
- dictionary, where the paramter ('--foo') is the key and it's argument
- ('bar') is the value.
+ if command == 'manpage':
+ import manpage
+ manpage.ManPage(self, handle, format, options)
- @param paramList: sequence of parameters (usually from self.ARGUMENTS)
- @return: dictionary of parameters, splitted by the first '='
- @raises StartupError: if a parameter has no value assigned
- """
+ # -------------------------------------------------------------------------
+ # Convert parameter sequence into dictionary
+ # -------------------------------------------------------------------------
- parameters = {}
- for param in [unicode(p, locale.getpreferredencoding()) for p in paramList]:
- psplit = param.split('=', 1)
- if len (psplit) == 1:
- raise StartupError, \
- 'Parameter "%s" specified, but no value supplied.' % psplit [0]
- parameters [psplit [0].lower()] = psplit [1]
+ def getCommandLineParameters(self, paramList):
+ """
+ Convert a sequence of parameters (i.e. '--foo=bar') into a parameter
+ dictionary, where the paramter ('--foo') is the key and it's argument
+ ('bar') is the value.
- assert gDebug (2,'Param "%s"="%s" ' % (psplit [0].lower(), psplit [1]))
+ @param paramList: sequence of parameters (usually from self.ARGUMENTS)
+ @return: dictionary of parameters, splitted by the first '='
- return parameters
+ @raises StartupError: if a parameter has no value assigned
+ """
+ parameters = {}
+ for param in [unicode(p, locale.getpreferredencoding()) \
+ for p in paramList]:
+ psplit = param.split('=', 1)
+ if len(psplit) == 1:
+ raise StartupError, \
+ 'Parameter "%s" specified, but no value supplied.' \
+ % psplit[0]
+ parameters[psplit[0].lower()] = psplit[1]
- # ---------------------------------------------------------------------------
- # Display a startup error and exit gracefully
- # ---------------------------------------------------------------------------
+ assert gDebug(2,'Param "%s"="%s" ' % (psplit[0].lower(), psplit[1]))
- def handleStartupError (self, msg):
- """
- Display a startup error and exit gracefully. This function is depreciated.
- Descendants should use the concpet of exceptions instead, which will be
- handled by the exception hook installed by this class.
- """
+ return parameters
- self.printVersion ()
- # if msg is multiline, then surround with dashes to set it apart
- if ("%s" % msg).find("\n") + 1:
- print '-' * 60
+ # -------------------------------------------------------------------------
+ # Display a startup error and exit gracefully
+ # -------------------------------------------------------------------------
- print o(u_("Error: %s") % msg)
- if ("%s" % msg).find("\n") + 1:
- print '-' * 60
+ def handleStartupError(self, msg):
+ """
+ Display a startup error and exit gracefully. This function is
+ depreciated. Descendants should use the concpet of exceptions instead,
+ which will be handled by the exception hook installed by this class.
+ """
- print o(u_("\nFor help, type:\n %s --help\n") % self.COMMAND)
+ self.printVersion()
- sys.exit ()
+ # if msg is multiline, then surround with dashes to set it apart
+ if ("%s" % msg).find("\n") + 1:
+ print '-' * 60
+ print o(u_("Error: %s") % msg)
+ if ("%s" % msg).find("\n") + 1:
+ print '-' * 60
- # ---------------------------------------------------------------------------
- # Display version information
- # ---------------------------------------------------------------------------
+ print o(u_("\nFor help, type:\n %s --help\n") % self.COMMAND)
- def doVersion (self):
- """
- Display the version information and quit the program.
- """
+ sys.exit()
- self.printVersion ()
- sys.exit ()
+ # -------------------------------------------------------------------------
+ # Display version information
+ # -------------------------------------------------------------------------
- # ---------------------------------------------------------------------------
- # Run the self documentation
- # ---------------------------------------------------------------------------
+ def doVersion(self):
+ """
+ Display the version information and quit the program.
+ """
- def doSelfDoc (self):
- """
- Run the self documentation. If a documentation file is specified the
- contents will be written to that file, otherwise it will be printed to
- stdout.
- """
+ self.printVersion()
+ sys.exit()
- if self.OPTIONS ['selfdoc-file']:
- doprint = False
- handle = open (self.OPTIONS ['selfdoc-file'], 'w')
- else:
- doprint = True
- import StringIO
- handle = StringIO.StringIO
- try:
- self.selfdoc (self.OPTIONS ['selfdoc'], handle,
- self.OPTIONS ['selfdoc-format'],
- self.OPTIONS ['selfdoc-options'])
- if doprint:
- handle.seek (0)
- print o(handle.read ())
+ # -------------------------------------------------------------------------
+ # Run the self documentation
+ # -------------------------------------------------------------------------
- finally:
- handle.close ()
+ def doSelfDoc(self):
+ """
+ Run the self documentation. If a documentation file is specified the
+ contents will be written to that file, otherwise it will be printed to
+ stdout.
+ """
- sys.exit ()
+ if self.OPTIONS['selfdoc-file']:
+ doprint = False
+ handle = open(self.OPTIONS['selfdoc-file'], 'w')
+ else:
+ doprint = True
+ import StringIO
+ handle = StringIO.StringIO
+ try:
+ self.selfdoc(self.OPTIONS['selfdoc'], handle,
+ self.OPTIONS['selfdoc-format'],
+ self.OPTIONS['selfdoc-options'])
+ if doprint:
+ handle.seek(0)
+ print o(handle.read())
- # ---------------------------------------------------------------------------
- # Display information about the configuration settings
- # ---------------------------------------------------------------------------
+ finally:
+ handle.close()
- def doHelpConfig (self):
- """
- Display all configuration settings and their default values and quit the
- program.
- """
+ sys.exit()
- self.printHelpHeader ()
- print o(GConfig.printableConfigOptions (self.configDefaults))
- sys.exit ()
+ # -------------------------------------------------------------------------
+ # Display information about the configuration settings
+ # -------------------------------------------------------------------------
+ def doHelpConfig(self):
+ """
+ Display all configuration settings and their default values and quit
+ the program.
+ """
- # ---------------------------------------------------------------------------
- # Catch an exception
- # ---------------------------------------------------------------------------
+ self.printHelpHeader()
+ print o(GConfig.printableConfigOptions(self.configDefaults))
- def excepthook (self, etype, value, traceback):
- """
- This function catches an exception and evaluates it using getException ().
- The exception-tuple is then passed to showException (), which might get
- overriden by a descendant.
- """
- sys.excepthook = sys.__excepthook__
- log.excepthook(etype, value, traceback)
- self._showException (*errors.getException (None, etype, value, traceback))
- sys.excepthook = self.excepthook
+ sys.exit()
- # ---------------------------------------------------------------------------
- # Used when interactive debugger in use
- # ---------------------------------------------------------------------------
+ # -------------------------------------------------------------------------
+ # Catch an exception
+ # -------------------------------------------------------------------------
- def _debugger (self):
- """
- Run the application in the python debugger.
- """
+ def excepthook(self, etype, value, traceback):
+ """
+ This function catches an exception and evaluates it using
+ getException(). The exception-tuple is then passed to showException(),
+ which might get overriden by a descendant.
+ """
+ sys.excepthook = sys.__excepthook__
+ log.excepthook(etype, value, traceback)
+ self._showException(*errors.getException(None, etype, value, traceback))
+ sys.excepthook = self.excepthook
- import pdb
- debugger = pdb.Pdb ()
- GDebug.setDebugger (debugger)
- debugger.runctx ('self._run ()', globals (), locals ())
+ # -------------------------------------------------------------------------
+ # Used when interactive debugger in use
+ # -------------------------------------------------------------------------
+ def _debugger(self):
+ """
+ Run the application in the python debugger.
+ """
- # ---------------------------------------------------------------------------
- # Used when profiling
- # ---------------------------------------------------------------------------
+ import pdb
- def _profile (self):
- """
- Run the application through the python profiler and print some statistics
- afterwards.
- """
+ debugger = pdb.Pdb()
+ GDebug.setDebugger(debugger)
+ debugger.runctx('self._run()', globals(), locals())
- import profile
- prof = profile.Profile ()
- prof.runctx ('self._run ()', globals (), locals ())
- import pstats
- p = pstats.Stats (prof)
- p.sort_stats ('time').print_stats (50)
- p.sort_stats ('cumulative').print_stats (50)
- p.sort_stats ('calls').print_stats (50)
+ # -------------------------------------------------------------------------
+ # Used when profiling
+ # -------------------------------------------------------------------------
+ def _profile(self):
+ """
+ Run the application through the python profiler and print some
+ statistics afterwards.
+ """
- # ---------------------------------------------------------------------------
- # Show an exception
- # ---------------------------------------------------------------------------
+ import profile
+ prof = profile.Profile()
+ prof.runctx('self._run()', globals(), locals())
- def _showException (self, group, name, message, detail):
- """
- This function shows an exception specified by the given parameters.
- @param group: Exception group ('system', 'admin', 'application', 'user')
- @param name: Name of the exception
- @param message: Message of the exception
- @param detail: Detail of the exception (usually holding a traceback)
- """
+ import pstats
+ p = pstats.Stats(prof)
+ p.sort_stats('time').print_stats(50)
+ p.sort_stats('cumulative').print_stats(50)
+ p.sort_stats('calls').print_stats(50)
- if group in ['user', 'admin']:
- sys.__stderr__.write ("%s: %s\n" % (self.COMMAND, o(message)))
- sys.__stderr__.write ("%s\n" % \
- o(u_("For help, type: %s --help") % self.COMMAND))
- else:
- sys.stderr.write ("%s\n" % o(detail))
+ # -------------------------------------------------------------------------
+ # Show an exception
+ # -------------------------------------------------------------------------
- # ---------------------------------------------------------------------------
- # Install a signal handler for SIGUSR1
- # ---------------------------------------------------------------------------
+ def _showException(self, group, name, message, detail):
+ """
+ This function shows an exception specified by the given parameters.
+ @param group: Exception group('system', 'admin', 'application', 'user')
+ @param name: Name of the exception
+ @param message: Message of the exception
+ @param detail: Detail of the exception(usually holding a traceback)
+ """
- def __installGCHandler (self):
- """
- Install a signal handler for SIGUSR1, which actually performs the debugging.
- """
+ if group in ['user', 'admin']:
+ sys.__stderr__.write("%s: %s\n" % (self.COMMAND, o(message)))
+ sys.__stderr__.write("%s\n" % \
+ o(u_("For help, type: %s --help") % self.COMMAND))
+ else:
+ sys.stderr.write("%s\n" % o(detail))
- signal.signal (signal.SIGUSR1, self.debugGarbageCollection)
+ # -------------------------------------------------------------------------
+ # Install a signal handler for SIGUSR1
+ # -------------------------------------------------------------------------
- # ---------------------------------------------------------------------------
- # Debug Python's garbage collection
- # ---------------------------------------------------------------------------
+ def __installGCHandler(self):
+ """
+ Install a signal handler for SIGUSR1, which actually performs the
+ debugging.
+ """
- def debugGarbageCollection (self, signal, frame):
- """
- Debug Python's garbage collection.
+ signal.signal(signal.SIGUSR1, self.debugGarbageCollection)
- @param signal: signal number caught by this handler (=SIGUSR1)
- @param frame: the current stack frame or None
- """
- filename = "garbage.log"
- if isinstance (self.OPTIONS ['debug-gc'], basestring):
- filename = self.OPTIONS ['debug-gc']
+ # -------------------------------------------------------------------------
+ # Debug Python's garbage collection
+ # -------------------------------------------------------------------------
- log = open (filename, 'w')
- try:
- # If we are interested in the objects collected by the garbage collection
- # set the debug level to gc.DEBUG_LEAK. In this case gc.garbage contains
- # all objects, collectable and uncollectable as well and we are able to
- # inspect those cycles and objects.
- gc.collect ()
+ def debugGarbageCollection(self, signal, frame):
+ """
+ Debug Python's garbage collection.
- self.__gcLog (log, "Number of unreachable objects: %d" % len (gc.garbage))
- if not gc.garbage:
- return
+ @param signal: signal number caught by this handler (=SIGUSR1)
+ @param frame: the current stack frame or None
+ """
- try:
- self.__gcLog (log, "Dump of gc.garbage sequence:")
- self.__gcLog (log, "-" * 70)
+ filename = "garbage.log"
+ if isinstance(self.OPTIONS['debug-gc'], basestring):
+ filename = self.OPTIONS['debug-gc']
- for item in gc.garbage:
- try:
- itemrep = "%s: %s" % (type (item), repr (item))
- except:
- itemrep = "No representation available for object (weakref/proxy?)"
+ log = open(filename, 'w')
+ try:
+ # If we are interested in the objects collected by the garbage
+ # collection set the debug level to gc.DEBUG_LEAK. In this case
+ # gc.garbage contains all objects, collectable and uncollectable as
+ # well and we are able to inspect those cycles and objects.
+ gc.collect()
- self.__gcLog (log, "%s" % itemrep)
+ self.__gc_log(log, "Number of unreachable objects: %d" % \
+ len(gc.garbage))
+ if not gc.garbage:
+ return
- for item in gc.garbage:
- cycle = self.findCycle (item, item, None, [], {})
+ try:
+ self.__gc_log(log, "Dump of gc.garbage sequence:")
+ self.__gc_log(log, "-" * 70)
- if cycle:
- self.__gcLog (log, "-" * 70)
+ for item in gc.garbage:
+ try:
+ itemrep = "%s: %s" % (type(item), repr(item))
+ except:
+ itemrep = "No representation available for " \
+ "object(weakref/proxy?)"
- for line in self.analyzeCycle (cycle):
- self.__gcLog (log, line)
+ self.__gc_log(log, "%s" % itemrep)
- self.__gcLog (log, "-" * 70)
+ for item in gc.garbage:
+ cycle = self.findCycle(item, item, None, [], {})
- finally:
- del gc.garbage [:]
+ if cycle:
+ self.__gc_log(log, "-" * 70)
- finally:
- log.close ()
+ for line in self.analyzeCycle(cycle):
+ self.__gc_log(log, line)
+ self.__gc_log(log, "-" * 70)
- # ---------------------------------------------------------------------------
+ finally:
+ del gc.garbage[:]
- def __gcLog (self, filehandle, message):
+ finally:
+ log.close()
- filehandle.write ("%s%s" % (message, os.linesep))
- print o(message)
+ # -------------------------------------------------------------------------
- # ---------------------------------------------------------------------------
- # Find a reference cycle starting from a given object
- # ---------------------------------------------------------------------------
+ def __gc_log(self, filehandle, message):
- def findCycle (self, search, current, last, path, seen):
- """
- Find a reference cycle starting from a given object (current) and ending
- with a given object (search). The result is either None if no such cycle
- exists, or a sequence of tuples (repr, propertyname) describing the
- reference cycle. 'repr' is either a string representation of an object
- holding the reference or None. 'propertyname' could be one of the
- following:
- - 'name': name of the property within 'repr' holding the reference
- - '[n]': the reference is the n-th element of a sequence
- - '[name]': the reference is the value of key 'name' in a dictionary
- - '{}': the reference is a key in a dictionary
+ filehandle.write("%s%s" % (message, os.linesep))
+ print o(message)
- The latter three variants could be cumulative (i.e. [1][3]['foo']) and the
- corresponding propertyname is the last one encountered.
- @return: None or sequence of tuples (repr, propertyname)
- """
+ # -------------------------------------------------------------------------
+ # Find a reference cycle starting from a given object
+ # -------------------------------------------------------------------------
- if last is not None:
- path = path + [last]
+ def findCycle(self, search, current, last, path, seen):
+ """
+ Find a reference cycle starting from a given object(current) and ending
+ with a given object(search). The result is either None if no such cycle
+ exists, or a sequence of tuples (repr, propertyname) describing the
+ reference cycle. 'repr' is either a string representation of an object
+ holding the reference or None. 'propertyname' could be one of the
+ following:
+ - 'name': name of the property within 'repr' holding the reference
+ - '[n]': the reference is the n-th element of a sequence
+ - '[name]': the reference is the value of key 'name' in a dictionary
+ - '{}': the reference is a key in a dictionary
- currentId = id (current)
+ The latter three variants could be cumulative (i.e. [1][3]['foo']) and
+ the corresponding propertyname is the last one encountered.
- # If we have already visited this object, no need to do further processing
- if seen.has_key (currentId):
- return None
+ @return: None or sequence of tuples (repr, propertyname)
+ """
- seen [currentId] = path
+ if last is not None:
+ path = path + [last]
- # If the current object has a __dict__ property, iterate over all it's
- # properties
- if hasattr (current, '__dict__'):
- for (name, attr) in current.__dict__.items ():
- prop = (repr (current), name)
+ currentId = id(current)
- if attr == search:
- return path + [prop]
+ # If we have already visited this object, no need to do further
+ # processing
+ if seen.has_key(currentId):
+ return None
- else:
- newpath = self.findCycle (search, attr, prop, path, seen)
- if newpath:
- return newpath
+ seen[currentId] = path
- # A bound method has a reference to self
- elif isinstance (current, types.MethodType):
- if current.im_self == search:
- return path + [(repr (current), "im_self")]
+ # If the current object has a __dict__ property, iterate over all it's
+ # properties
+ if hasattr(current, '__dict__'):
+ for (name, attr) in current.__dict__.items():
+ prop = (repr(current), name)
- # For Sequences or Tuples iterate over all elements
- elif isinstance (current, types.ListType) or \
- isinstance (current, types.TupleType):
+ if attr == search:
+ return path + [prop]
- for (index, element) in enumerate (current):
- prop = (None, "[%d]" % index)
- if element == search:
- return path + [prop]
+ else:
+ newpath = self.findCycle(search, attr, prop, path, seen)
+ if newpath:
+ return newpath
- else:
- newpath = self.findCycle (search, element, prop, path, seen)
- if newpath:
- return newpath
+ # A bound method has a reference to self
+ elif isinstance(current, types.MethodType):
+ if current.im_self == search:
+ return path + [(repr(current), "im_self")]
- # For dictionaries iterate over all items
- elif isinstance (current, types.DictType):
- for (key, element) in current.items ():
- prop = (None, "[%s]" % repr (key))
+ # For Sequences or Tuples iterate over all elements
+ elif isinstance(current, types.ListType) or \
+ isinstance(current, types.TupleType):
- if element == search:
- return path + [prop]
+ for (index, element) in enumerate(current):
+ prop = (None, "[%d]" % index)
+ if element == search:
+ return path + [prop]
- elif key == search:
- return path + [(None, "{}")]
+ else:
+ newpath = self.findCycle(search, element, prop, path, seen)
+ if newpath:
+ return newpath
- else:
- newpath = self.findCycle (search, element, prop, path, seen)
- if newpath:
- return newpath
+ # For dictionaries iterate over all items
+ elif isinstance(current, types.DictType):
+ for (key, element) in current.items():
+ prop = (None, "[%s]" % repr(key))
- # a generator keeps has always reference to self, so we have to iterate
- # it's local namespace
- elif isinstance (current, types.GeneratorType):
- for (key, element) in current.gi_frame.f_locals.items ():
- prop = (None, "[%s]" % key)
- if element == search:
- return path + [prop]
+ if element == search:
+ return path + [prop]
- elif key == search:
- return path + [(None, "{}")]
+ elif key == search:
+ return path + [(None, "{}")]
- else:
- newpath = self.findCycle (search, element, prop, path, seen)
- if newpath:
- return newpath
+ else:
+ newpath = self.findCycle(search, element, prop, path, seen)
+ if newpath:
+ return newpath
- return None
+ # a generator keeps has always reference to self, so we have to iterate
+ # it's local namespace
+ elif isinstance(current, types.GeneratorType):
+ for (key, element) in current.gi_frame.f_locals.items():
+ prop = (None, "[%s]" % key)
+ if element == search:
+ return path + [prop]
+ elif key == search:
+ return path + [(None, "{}")]
- # ---------------------------------------------------------------------------
- # Analyze a given reference cycle
- # ---------------------------------------------------------------------------
+ else:
+ newpath = self.findCycle(search, element, prop, path, seen)
+ if newpath:
+ return newpath
- def analyzeCycle (self, cycle):
- """
- Return a generator for iterating a given reference cycle.
+ return None
- @param cycle: None or a sequence of tuples (repr, propertyname)
- @return: iterator
- """
- if cycle:
- for (index, (rep, name)) in enumerate (cycle):
- if index == 0:
- yield 'self = %s' % rep
- lastname = 'self.%s' % name
- else:
- if rep is not None:
- yield '%s = %s' % (lastname, rep)
- jsymb = '.'
- else:
- jsymb = ' '
+ # -------------------------------------------------------------------------
+ # Analyze a given reference cycle
+ # -------------------------------------------------------------------------
- lastname = jsymb.join ([lastname, name])
+ def analyzeCycle(self, cycle):
+ """
+ Return a generator for iterating a given reference cycle.
- yield '%s = self' % lastname
+ @param cycle: None or a sequence of tuples (repr, propertyname)
+ @return: iterator
+ """
+ if cycle:
+ for (index, (rep, name)) in enumerate(cycle):
+ if index == 0:
+ yield 'self = %s' % rep
+ lastname = 'self.%s' % name
+ else:
+ if rep is not None:
+ yield '%s = %s' % (lastname, rep)
+ jsymb = '.'
+ else:
+ jsymb = ' '
+
+ lastname = jsymb.join([lastname, name])
+
+ yield '%s = self' % lastname
Modified: trunk/gnue-common/src/apps/GDebug.py
===================================================================
--- trunk/gnue-common/src/apps/GDebug.py 2007-09-27 08:57:00 UTC (rev 9785)
+++ trunk/gnue-common/src/apps/GDebug.py 2007-09-27 12:37:18 UTC (rev 9786)
@@ -28,7 +28,7 @@
import sys, os
if '--debug-imports' in sys.argv or os.environ.has_key('GNUE_DEBUG_IMPORT'):
- from gnue.common.apps import GImportLogger
+ from gnue.common.apps import GImportLogger
import __builtin__
import inspect
@@ -38,6 +38,7 @@
import time
import traceback
import types
+import logging
from gnue.common.base import log
@@ -58,14 +59,14 @@
# -----------------------------------------------------------------------------
def __noDebug (level, message):
- return True
-
+ return True
+
def __noEnter (level = 1):
- return True
+ return True
def __noLeave (level = 1, *result):
- return True
+ return True
# Initialize builtin dictionary with placeholders until setDebug is called
__builtin__.__dict__ ['gDebug'] = __noDebug
@@ -78,121 +79,121 @@
# -----------------------------------------------------------------------------
def gDebug (level, message, *args):
- """
- Write a message to the debug-output. This function is available in the
- global namespace.
+ """
+ Write a message to the debug-output. This function is available in the
+ global namespace.
- @param level: the debug-level the message will be logged in
- @param message: the message to be logged
- @return: Always true so it can be filtered out via assert
- """
+ @param level: the debug-level the message will be logged in
+ @param message: the message to be logged
+ @return: Always true so it can be filtered out via assert
+ """
- if level in _DEBUG_LEVELS:
- log.debug_n(inspect.stack()[1][0].f_globals['__name__'], message)
+ if level in _DEBUG_LEVELS:
+ log.debug_n(inspect.stack()[1][0].f_globals['__name__'], message)
- return True
+ return True
# -----------------------------------------------------------------------------
# Add a function-signature to the debug output
# -----------------------------------------------------------------------------
def gEnter (level = 1):
- """
- Write information about the current function and its parameters to
- debug-output. This function is available in the global namespace.
+ """
+ Write information about the current function and its parameters to
+ debug-output. This function is available in the global namespace.
- assert gEnter is intended to be called at the begin of a function.
+ assert gEnter is intended to be called at the begin of a function.
- @param level: the debug-level the message will be logged in
- @return: Always true so it can be filtered out via assert
- """
+ @param level: the debug-level the message will be logged in
+ @return: Always true so it can be filtered out via assert
+ """
- if not level in _DEBUG_LEVELS:
- return True
+ if not level in _DEBUG_LEVELS:
+ return True
- # Get the caller's frame
- frame = sys._getframe (1)
+ # Get the caller's frame
+ frame = sys._getframe (1)
- try:
- (args, vargs, vkw, flocals) = inspect.getargvalues (frame)
+ try:
+ (args, vargs, vkw, flocals) = inspect.getargvalues (frame)
- # If the function has a 'self' argument we add the class referenced by self
- # to the name of the function
- funcName = frame.f_code.co_name
- if 'self' in args:
- funcName = "%s.%s" % (flocals ['self'].__class__, funcName)
+ # If the function has a 'self' argument we add the class referenced by
+ # self to the name of the function
+ funcName = frame.f_code.co_name
+ if 'self' in args:
+ funcName = "%s.%s" % (flocals ['self'].__class__, funcName)
- params = []
+ params = []
- # First add all 'normal' arguments
- params = [repr (flocals [item]) for item in args]
+ # First add all 'normal' arguments
+ params = [repr (flocals [item]) for item in args]
- # Next, add all variable arguments (*arg)
- if vargs:
- params.extend ([repr (i) for i in flocals [vargs]])
+ # Next, add all variable arguments (*arg)
+ if vargs:
+ params.extend ([repr (i) for i in flocals [vargs]])
- # and finally add all keyword arguments (**kwarg)
- if vkw is not None:
- params.extend (["%s = %s" % (repr (k), repr (v)) \
- for (k, v) in flocals [vkw].items ()])
+ # and finally add all keyword arguments (**kwarg)
+ if vkw is not None:
+ params.extend (["%s = %s" % (repr (k), repr (v)) \
+ for (k, v) in flocals [vkw].items ()])
- message = "Entering function %s (%s)" % (funcName,
- string.join (params, ", "))
+ message = "Entering function %s (%s)" % (funcName,
+ string.join (params, ", "))
- log.debug_n(inspect.stack()[1][0].f_globals['__name__'], message)
+ log.debug_n(inspect.stack()[1][0].f_globals['__name__'], message)
- finally:
- # Make sure to release the reference to the frame object. This keeps
- # garbage collection doing a fine job :)
- del frame
-
- return True
+ finally:
+ # Make sure to release the reference to the frame object. This keeps
+ # garbage collection doing a fine job :)
+ del frame
+ return True
+
# -----------------------------------------------------------------------------
# Add a line to debug-output describing the end of a function call
# -----------------------------------------------------------------------------
def gLeave (level = 1, *result):
- """
- Write information about the current function and its return value to
- debug-output. This function is available in the global namespace.
+ """
+ Write information about the current function and its return value to
+ debug-output. This function is available in the global namespace.
- gLeave is intended to be called at the end of a function.
+ gLeave is intended to be called at the end of a function.
- @param level: debug-level to send the message to
- @param result: the function's result (if any)
- @return: True
- """
+ @param level: debug-level to send the message to
+ @param result: the function's result (if any)
+ @return: True
+ """
- if not level in _DEBUG_LEVELS:
- return True
+ if not level in _DEBUG_LEVELS:
+ return True
- # Get the caller's frame
- frame = sys._getframe (1)
+ # Get the caller's frame
+ frame = sys._getframe (1)
- try:
- (args, vargs, vkw, flocals) = inspect.getargvalues (frame)
+ try:
+ (args, vargs, vkw, flocals) = inspect.getargvalues (frame)
- # If the function has a 'self' argument we add the class referenced by self
- # to the name of the function
- fName = frame.f_code.co_name
- hId = ''
- if 'self' in args:
- fName = "%s.%s" % (flocals ['self'].__class__, fName)
- hId = repr (hex (id (flocals ['self'])))
+ # If the function has a 'self' argument we add the class referenced by
+ # self to the name of the function
+ fName = frame.f_code.co_name
+ hId = ''
+ if 'self' in args:
+ fName = "%s.%s" % (flocals ['self'].__class__, fName)
+ hId = repr (hex (id (flocals ['self'])))
- resStr = len (result) and ' == %s' % repr (result [0]) or ''
- message = "Leaving function %s (%s)%s" % (fName, hId, resStr)
+ resStr = len (result) and ' == %s' % repr (result [0]) or ''
+ message = "Leaving function %s (%s)%s" % (fName, hId, resStr)
- log.debug_n(inspect.stack()[1][0].f_globals['__name__'], message)
+ log.debug_n(inspect.stack()[1][0].f_globals['__name__'], message)
- finally:
- # Make sure to release the reference to the frame object. This keeps
- # garbage collection doing a fine job :)
- del frame
+ finally:
+ # Make sure to release the reference to the frame object. This keeps
+ # garbage collection doing a fine job :)
+ del frame
- return True
+ return True
# -----------------------------------------------------------------------------
@@ -200,40 +201,45 @@
# -----------------------------------------------------------------------------
def setDebug (level, file = None):
- """
- Initialize and configure the debug message system
+ """
+ Initialize and configure the debug message system
- @param level: A string with the debug levels to output, e.g. "0-3,5,7"
- @param file: Filename to output debug messages to (instead of stderr)
- """
+ @param level: A string with the debug levels to output, e.g. "0-3,5,7"
+ @param file: Filename to output debug messages to (instead of stderr)
+ """
- global _DEBUG_LEVELS, printMesg
+ global _DEBUG_LEVELS, printMesg
- # Find out debug levels
- levels = []
- for entry in level.split(','):
- values=entry.split('-')
- if len(values) > 1:
- levels+=range(int(values[0]),int(values[1])+1)
- else:
- levels+=[int(entry)]
+ # Find out debug levels
+ levels = []
+ for entry in level.split(','):
+ values=entry.split('-')
+ if len(values) > 1:
+ levels+=range(int(values[0]),int(values[1])+1)
+ else:
+ levels+=[int(entry)]
- _DEBUG_LEVELS=levels
+ _DEBUG_LEVELS=levels
- # If debug levels are given, we must replace the empty placeholder functions
- # with a function that actually does something
- if _DEBUG_LEVELS != []:
- __builtin__.__dict__ ['gDebug'] = gDebug
- __builtin__.__dict__ ['gEnter'] = gEnter
- __builtin__.__dict__ ['gLeave'] = gLeave
+ # If debug levels are given, we must replace the empty placeholder
+ # functions with a function that actually does something
+ if _DEBUG_LEVELS != []:
+ __builtin__.__dict__ ['gDebug'] = gDebug
+ __builtin__.__dict__ ['gEnter'] = gEnter
+ __builtin__.__dict__ ['gLeave'] = gLeave
+ if file is not None:
+ lgr = logging.getLogger('gnue')
+ lgr.addHandler(logging.FileHandler(file, 'a+'))
+ lgr.setLevel(logging.DEBUG)
+
# -----------------------------------------------------------------------------
# Deprecated, for compatibility
# -----------------------------------------------------------------------------
def printMesg (level, message):
- """
- This function is deprecated - use gDebug instead
- """
- __builtin__.__dict__ ['gDebug'] (level, message)
+ """
+ This function is deprecated - use gDebug instead
+ """
+ __builtin__.__dict__ ['gDebug'] (level, message)
lmpx.com only provides a reader for public news (NNTP) servers. It is not
affiliated with the servers or forums shown here and is not responsible for
the content of articles, which is written by their respective authors.