# HG changeset patch # User David Anderson # Date 1236968094 0 # Node ID 0589bf1395c567b61228f947f0bd6377aeea524d # Parent 9df2e9a6708125628d5bd610db30750043a9243d Add a log module to initialize and manage logging. diff -r 9df2e9a67081 -r 0589bf1395c5 scripts/release/log.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/scripts/release/log.py Fri Mar 13 18:14:54 2009 +0000 @@ -0,0 +1,78 @@ +# Copyright 2009 the Melange authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""Logging facilities. + +The public interface is basically an initialization function for the +underlying Python logging module. Logging always goes to the console, +and can optionally be configured to write to a transcript file, which +will store exactly what appears on screen (minus colors). +""" + +__authors__ = [ + # alphabetical order by last name, please + '"David Anderson" ', + ] + +import logging + +import util + + +class _ColorizingFormatter(logging.Formatter): + """A logging formatter that colorizes based on log levels.""" + + def format(self, record): + msg = logging.Formatter.format(self, record) + + if record.levelno >= logging.WARNING: + return util.colorize(msg, util.RED, bold=True) + elif record.levelno == logging.INFO: + return util.colorize(msg, util.GREEN) + else: + return msg + + +class _DecolorizingFormatter(logging.Formatter): + """A logging formatter that strips color.""" + + def format(self, record): + return util.decolorize(logging.Formatter.format(self, record)) + + +def init(logfile=None): + """Initialize the logging subsystem. + + Args: + logfile: The filename for the transcript file, if any. + """ + + root = logging.getLogger('') + root.setLevel(logging.DEBUG) + + console = logging.StreamHandler() + console.setLevel(logging.DEBUG) + console.setFormatter(_ColorizingFormatter()) + root.addHandler(console) + + if logfile: + transcript = logging.FileHandler(logfile, 'w') + transcript.setLevel(logging.DEBUG) + transcript.setFormatter(_DecolorizingFormatter()) + root.addHandler(transcript) + + +debug = logging.debug +info = logging.info +error = logging.error diff -r 9df2e9a67081 -r 0589bf1395c5 scripts/release/release.py --- a/scripts/release/release.py Fri Mar 13 18:14:44 2009 +0000 +++ b/scripts/release/release.py Fri Mar 13 18:14:54 2009 +0000 @@ -48,6 +48,7 @@ import sys import error +import log import util @@ -82,16 +83,6 @@ """An error occured while accessing a file.""" -def error(msg): - """Log an error message.""" - print util.colorize(msg, util.RED, bold=True) - - -def info(msg): - """Log an informational message.""" - print util.colorize(msg, util.GREEN) - - def confirm(prompt, default=False): """Ask a yes/no question and return the answer. @@ -121,7 +112,7 @@ elif answer in ('n', 'no'): return False else: - error('Please answer yes or no.') + log.error('Please answer yes or no.') def getString(prompt): @@ -142,7 +133,7 @@ try: return int(value_str) except ValueError: - error('Please enter a number. You entered "%s".' % value_str) + log.error('Please enter a number. You entered "%s".' % value_str) def getChoice(intro, prompt, choices, done=None, suggest=None): @@ -174,8 +165,8 @@ choice = getNumber(prompt) if 0 < choice <= len(choices): return choice-1 - error('%d is not a valid choice between %d and %d' % - (choice, 1, len(choices))) + log.error('%d is not a valid choice between %d and %d' % + (choice, 1, len(choices))) print @@ -544,7 +535,7 @@ the end state is a fully ready to function release environment. """ - info('Checking out the release repository') + log.info('Checking out the release repository') # Check out a sparse view of the relevant repository paths. self.wc.checkout(self.release_repos, depth='immediates') @@ -598,7 +589,7 @@ if release is None: self.branch = None self.branch_dir = None - info('No release branch available') + log.info('No release branch available') else: self.wc.update() assert self.wc.exists('branches/' + release) @@ -606,7 +597,7 @@ self.branch = release self.branch_dir = 'branches/' + release self.wc.update(self.branch_dir, depth='infinity') - info('Working on branch ' + self.branch) + log.info('Working on branch ' + self.branch) def _branchPath(self, path): """Return the given path with the release branch path prepended.""" @@ -729,7 +720,7 @@ self._applyGooglePatches() # All done! - info('Melange release %s imported and googlified' % self.branch) + log.info('Melange release %s imported and googlified' % self.branch) @requires_branch @pristine_wc @@ -764,17 +755,17 @@ out.append(line) if not updated_patchlevel: - error('Failed to update Google patch revision') - error('Cherry-picking failed') + log.error('Failed to update Google patch revision') + log.error('Cherry-picking failed') linesToFile(yaml_path, out) - info('Check the diff about to be committed with:') - info('svn diff ' + self.wc.path(self.branch_dir)) + log.info('Check the diff about to be committed with:') + log.info('svn diff ' + self.wc.path(self.branch_dir)) if not confirm('Commit this change?'): raise AbortedByUser('Cherry-pick aborted') self.wc.commit(message) - info('Cherry-picked r%d from the Melange trunk.' % rev) + log.info('Cherry-picked r%d from the Melange trunk.' % rev) MENU_ORDER = [ update, @@ -813,12 +804,12 @@ self.MENU_STRINGS, done=done, suggest=suggested_next) except (KeyboardInterrupt, AbortedByUser): - info('Exiting.') + log.info('Exiting.') return try: self.MENU_ORDER[choice](self) except Error, e: - error(str(e)) + log.error(str(e)) else: done.append(choice) last_choice = choice @@ -836,8 +827,10 @@ if len(argv) == 3: upstream_repos = argv[2] - info('Release repository: ' + release_repos) - info('Upstream repository: ' + upstream_repos) + log.init('release.log') + + log.info('Release repository: ' + release_repos) + log.info('Upstream repository: ' + upstream_repos) r = ReleaseEnvironment(os.path.abspath('_release_'), release_repos,