Source code for src.core.progress
"""A tool for processing information about an experiment's status."""
import logging
import textwrap
from time import strftime
log = logging.getLogger('transport')
[docs]class StatusMonitor(object):
"""A class for monitoring and displaying information to the user.
Many actions performed by instruments can take a significant amount of
execution time, and the user will typically want some information
about what is happening at a given moment.
This class allows information to be passed from the instruments (and the
experiment or actions) and processed via `Command` objects, allowing the
information to be redirected according to the program in question.
"""
def __init__(self, name, timestampUpdate=False, timestampPost=True):
self._name = name
self._past = []
self._current = ''
self._timestampUpdate = timestampUpdate
self._timestampPost = timestampPost
self._updateCommands = []
self._postCommands = []
[docs] def setName(self, name):
"""Set the name of the status monitor.
Parameters
----------
name : str
The new name for the status monitor.
"""
self._name = name
[docs] def getName(self):
"""Return the name of the status monitor.
Returns
-------
str
The name of the status monitor.
"""
return self._name
[docs] def setCommands(self, updateCommands=None, postCommands=None):
"""Set the commands which will be executed upon updates.
Parameters
----------
updateCommands : list of Command
A list of `Command` objects to be executed when the `update`
method is executed. `currentMessage`, a string, will be passed as
a keyword argument to each `Command`.
postCommands : list of Command
A list of `Command` objects to be executed when the `post` method
is executed. `postedMessage`, a string indicating the last completed
action, will be passed as a keyword argument to each `Command`.
"""
if updateCommands is None:
self._updateCommands = []
else:
self._updateCommands = updateCommands
if postCommands is None:
self._postCommands = []
else:
self._postCommands = postCommands
[docs] def update(self, message):
"""Update the message indicating the experiment's current state.
Parameters
----------
message : str
A string indicating the experiment's current status.
"""
self._current = message
for command in self._updateCommands:
command.execute(currentMessage=message)
[docs] def post(self, message=None):
"""Update the list of messages detailing the experiment's past actions.
Parameters
----------
message : str
A string which should be tacked onto the list of past actions. If
`None`, the last update will be sent to the past message list.
Regardless, the current status message will be cleared.
"""
if message is None:
self._past.append(strftime('%Y-%m-%d %H:%M:%S - ') + self._current)
else:
self._past.append(strftime('%Y-%m-%d %H:%M:%S - ') + message)
self._current = ''
notice = self._past[-1]
for command in self._postCommands:
command.execute(postedMessage=notice)
[docs] def clear(self):
"""Clear the status monitor's information."""
self._current = ''
self._past = []
self._updateCommands = []
self._postCommands = []
[docs]class TextPrompter(object):
"""An object for prompting for user input from the command line."""
def __init__(self, width=70):
self._width = width
[docs] def prompt(self, prompt, options):
"""Prompt the user for input."""
while True:
print textwrap.fill(prompt, self._width)
self._printOptions(options)
try:
response = int(raw_input('Enter a selection: '))
if 0 <= response < len(options):
return response
else:
print 'Choice %d is out of range. Try again.' % response
except (TypeError, ValueError):
print 'Invalid response. Try again.'
def _printOptions(self, options):
"""Print the available options."""
formatString = '%' + str(len(str(len(options))) + 2) + 'd : %s'
for i, item in enumerate(options):
print formatString % (i, item)
_STATUS_MONITORS = {}
[docs]def getStatusMonitor(name):
"""Return a status monitor, creating it if it does not exist.
Parameters
----------
name : str
The name of the status monitor to get.
Returns
-------
StatusMonitor
The `StatusMonitor` object with the specified name.
"""
if name in _STATUS_MONITORS:
return _STATUS_MONITORS[name]
newMonitor = StatusMonitor(name)
_STATUS_MONITORS[name] = newMonitor
return newMonitor