Source code for AutoArchive._ui._cmdline._core.cmdline_ui_component

# cmdline_ui_component.py
#
# Project: AutoArchive
# License: GNU GPLv3
#
# Copyright (C) 2003 - 2012 Róbert Čerňanský



""":class:`CmdlineUiComponent` class."""



__all__ = ["CmdlineUiComponent"]



# {{{ INCLUDES

import sys
import os

from ...._py_additions import *
from ...._mainf import *
from ...._configuration import *
from .. import *
from ._user_action_executor import *

# }}} INCLUDES



# {{{ CLASSES

[docs]class CmdlineUiComponent(IComponent, IComponentUi): """Implementation of the command-line user interface. Class serves as the component of :term:`Mainf` framework and uses the :meth:`run()` method as an entry point for executing user actions specified on the command-line. It implements the :class:`.IComponentUi` such that it uses standard output and standard error as the user interface. The instance is exposed as :class:`.IComponentInterface`.""" #: Maximal length of the archive name in output messages. __MAX_NAME_LENGTH = 10 # {{{ IComponent implementation def __init__(self, interfaceAccessor): self.__interfaceAccessor = interfaceAccessor self.__appConfig = self.__interfaceAccessor.getComponentInterface(IAppConfig) self.__appEnvironment = None self.__userActionExecutor = None # overall backup result self.__backupStatus = None
[docs] def run(self): """Executes an action defined for the specified command. Command is read from the :attr:`.IMainfContext.appEnvironment.options`. If ``options`` has an attribute that matches one of the :class:`.CmdlineCommands` and the value of that attribute is ``True`` then the action for the matching command is executed. If there is no such attribute, then the default action ``create`` is executed. :attr:`.CmdlineCommands.CREATE` command triggers the ``Create`` action. It takes all specified :term:`archive specification files <archive specification file>` and for each it creates a backup using :term:`Archiving` component. Archive specification files can be specified by following ways: - By archive names passed in :attr:`.IMainfContext.appEnvironment.arguments`. Archive name can not contain the string defined by :attr:`.ConfigConstants.ARCHIVE_SPEC_EXT` at the end otherwise it would be taken as the path to an archive specification file. Archive specification files corresponding to the names are looked up in the path defined by :attr:`.Options.ARCHIVE_SPECS_DIR` option. - By paths to archive specification files passed in :attr:`.IMainfContext.appEnvironment.arguments`. A path must end with the string defined by :attr:`.ConfigConstants.ARCHIVE_SPEC_EXT`. - By passing empty :attr:`.IMainfContext.appEnvironment.arguments` and setting the option :attr:`.Options.ALL` to ``True``. In this case the action shall be executed for all known archives as served by Configuration component (typically all archive specification files in :attr:`.Options.ARCHIVE_SPECS_DIR` directory). :attr:`.CmdlineCommands.LIST` command triggers the ``List`` action. It lists information about :term:`selected <selected archive>` and :term:`orphaned <orphaned archive>` archives to standard output. Archives can be specified by the same way as for the ``Create`` action except the last point where the ``List`` action does not require the option :attr:`.Options.ALL` to be ``True``. Orphaned archives are always listed. List of orphaned archives is obtained by following operation: from the list of :term:`stored archives <stored archive>` (as served by :term:`Archiving` component) is subtracted the unique list of valid selected archives and valid :term:`configured archives <configured archive>`. Output has two possible formats depending on the :attr:`.Options.VERBOSE` option. :attr:`.CmdlineCommands.PURGE` command triggers the ``Purge`` action. It removes all stored information about specified orphaned archives. Orphaned archives names can be passed in :attr:`.IMainfContext.appEnvironment.arguments` or if :attr:`.Options.ALL` is ``True`` then all orphaned archives are processed. See also: :meth:`.IComponent.run`.""" mainfContext = self.__interfaceAccessor.getComponentInterface(IMainfContext) self.__appEnvironment = mainfContext.appEnvironment self.__interfaceAccessor.registerComponentInterface(IComponentUi, self) self.__userActionExecutor = _UserActionExecutor(self.__interfaceAccessor) return self.__userActionExecutor.execute()
# }}} IComponent implementation # {{{ IComponentUi implementation @event def messageShown(messageKind): "See: :meth:`.IComponentUi.messageShown`." pass @property def verbosity(self): "See: :attr:`.IComponentUi.verbosity`." if self.__appConfig[Options.QUIET]: return VerbosityLevels.Quiet elif self.__appConfig[Options.VERBOSE]: return VerbosityLevels.Verbose return VerbosityLevels.Normal
[docs] def showVerbose(self, msg): "See: :meth:`.IComponentUi.showVerbose`." if self.verbosity == VerbosityLevels.Verbose: self.__printStandardMsg(msg) self.messageShown(UiMessageKinds.Verbose)
[docs] def showNotification(self, msg): "See: :meth:`.IComponentUi.showNotification`." if self.verbosity != VerbosityLevels.Quiet: self.__printStandardMsg(msg) self.messageShown(UiMessageKinds.Notification)
[docs] def showInfo(self, msg): "See: :meth:`.IComponentUi.showInfo`." if self.verbosity != VerbosityLevels.Quiet: self.__printStandardMsg(msg, self.__userActionExecutor.processedArchSpec) self.messageShown(UiMessageKinds.Info)
[docs] def showWarning(self, msg): "See: :meth:`.IComponentUi.showWarning`." if self.verbosity != VerbosityLevels.Quiet: self.__printAttentionMsg("Warning", msg) self.messageShown(UiMessageKinds.Warning)
[docs] def showError(self, msg): "See: :meth:`.IComponentUi.showError`." self.__printAttentionMsg("Error", msg) self.messageShown(UiMessageKinds.Error)
[docs] def presentLine(self, line): "See: :meth:`.IComponentUi.presentLine`." self.__printStandardMsg(line)
# }}} IComponentUi implementation # {{{ helpers @classmethod def __printStandardMsg(cls, msg, currentArchSpec = None): archSpecToken = str.format( "[{}] ", cls.__getArchSpecToken(currentArchSpec)) if currentArchSpec is not None else "" print(str.format("{}{}", archSpecToken, msg)) def __printAttentionMsg(self, attentionString, msg): archSpecToken = str.format( " [{}] ", self.__getArchSpecToken(self.__userActionExecutor.processedArchSpec)) \ if self.__userActionExecutor.processedArchSpec is not None else " " sys.stderr.write(str.format( "{executableName}: {attentionString}!{archSpecToken}{msg}\n", executableName = self.__appEnvironment.executableName, attentionString = attentionString, archSpecToken = archSpecToken, msg = msg)) @classmethod def __getArchSpecToken(cls, currentArchSpec): if os.path.split(currentArchSpec)[0]: return os.path.join(cls._shortenString(os.path.split(currentArchSpec)[0], cls.__MAX_NAME_LENGTH), os.path.basename(currentArchSpec)) else: return currentArchSpec @staticmethod def _shortenString(token, length): halfLength = length // 2 return token[:halfLength] + "~" + token[-halfLength - ((length % 2) - 1):] if len(token) > length else token
# }}} helpers # }}} CLASSES