diff -r db7c98580008 -r 8cfb054b73b2 scripts/release/io.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/scripts/release/io.py Sat Mar 21 17:12:07 2009 +0000 @@ -0,0 +1,144 @@ +#!/usr/bin/python2.5 +# +# 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. + +from __future__ import with_statement + +"""User prompting and file access utilities.""" + +__authors__ = [ + # alphabetical order by last name, please + '"David Anderson" ', + ] + +import error +import log + + +class Error(error.Error): + pass + + +class FileAccessError(Error): + """An error occured while accessing a file.""" + pass + + +def getString(prompt): + """Prompt for and return a string.""" + prompt += ' ' + log.stdout.write(prompt) + log.stdout.flush() + + response = sys.stdin.readline() + log.terminal_echo(prompt + response.strip()) + if not response: + raise error.AbortedByUser('Aborted by ctrl+D') + + return response.strip() + + +def confirm(prompt, default=False): + """Ask a yes/no question and return the answer. + + Will reprompt the user until one of "yes", "no", "y" or "n" is + entered. The input is case insensitive. + + Args: + prompt: The question to ask the user. + default: The answer to return if the user just hits enter. + + Returns: + True if the user answered affirmatively, False otherwise. + """ + if default: + question = prompt + ' [Yn]' + else: + question = prompt + ' [yN]' + while True: + answer = getString(question) + if not answer: + return default + elif answer in ('y', 'yes'): + return True + elif answer in ('n', 'no'): + return False + else: + log.error('Please answer yes or no.') + + +def getNumber(prompt): + """Prompt for and return a number. + + Will reprompt the user until a number is entered. + """ + while True: + value_str = getString(prompt) + try: + return int(value_str) + except ValueError: + log.error('Please enter a number. You entered "%s".' % value_str) + + +def getChoice(intro, prompt, choices, done=None, suggest=None): + """Prompt for and return a choice from a menu. + + Will reprompt the user until a valid menu entry is chosen. + + Args: + intro: Text to print verbatim before the choice menu. + prompt: The prompt to print right before accepting input. + choices: The list of string choices to display. + done: If not None, the list of indices of previously + selected/completed choices. + suggest: If not None, the index of the choice to highlight as + the suggested choice. + + Returns: + The index in the choices list of the selection the user made. + """ + done = set(done or []) + while True: + print intro + print + for i, entry in enumerate(choices): + done_text = ' (done)' if i in done else '' + indent = '--> ' if i == suggest else ' ' + print '%s%2d. %s%s' % (indent, i+1, entry, done_text) + print + choice = getNumber(prompt) + if 0 < choice <= len(choices): + return choice-1 + log.error('%d is not a valid choice between %d and %d' % + (choice, 1, len(choices))) + print + + +def fileToLines(path): + """Read a file and return it as a list of lines.""" + try: + with file(path) as f: + return f.read().split('\n') + except (IOError, OSError), e: + raise FileAccessError(str(e)) + + +def linesToFile(path, lines): + """Write a list of lines to a file.""" + try: + with file(path, 'w') as f: + f.write('\n'.join(lines)) + except (IOError, OSError), e: + raise FileAccessError(str(e))