File: C:/Users/fred/anaconda3/Lib/site-packages/anaconda_project/frontend.py
# -*- coding: utf-8 -*-
# -----------------------------------------------------------------------------
# Copyright (c) 2016, Anaconda, Inc. All rights reserved.
#
# Licensed under the terms of the BSD 3-Clause License.
# The full license is in the file LICENSE.txt, distributed with this software.
# -----------------------------------------------------------------------------
"""Frontend class representing a UX."""
from __future__ import absolute_import
from abc import ABCMeta, abstractmethod
from anaconda_project.internal.metaclass import with_metaclass
class Frontend(with_metaclass(ABCMeta)):
"""A UX (CLI, GUI, etc.) for project operations."""
def __init__(self):
"""Construct a Frontend."""
self._info_buf = ''
self._error_buf = ''
def _partial(self, data, buf, line_handler):
buf = buf + data
(start, sep, end) = buf.partition('\n')
while sep != '':
# we do this instead of using os.linesep in case
# something on windows outputs unix-style line
# endings, we don't want to go haywire. On unix when
# we actually want \r to carriage return, we'll be
# overriding this "partial" handler and not using this
# buffering implementation.
if start.endswith('\r'):
start = start[:-1]
line_handler(start)
buf = end
(start, sep, end) = buf.partition('\n')
return buf
def partial_info(self, data):
"""Log only part of an info-level line.
The default implementation buffers this until a line separator
and then passes the entire line to info().
Subtypes can override this if they want to print output
immediately as it arrives.
"""
self._info_buf = self._partial(data, self._info_buf, self.info)
def partial_error(self, data):
"""Log only part of an error-level line.
The default implementation buffers this until a line separator
and then passes the entire line to error().
Subtypes can override this if they want to print output
immediately as it arrives.
"""
self._error_buf = self._partial(data, self._error_buf, self.error)
@abstractmethod
def info(self, message):
"""Log an info-level message."""
pass # pragma: no cover
@abstractmethod
def error(self, message):
"""Log an error-level message.
A rule of thumb is that if a function also returns a
``Status``, this message should also be appended to the
``errors`` field on that status.
"""
pass # pragma: no cover
# @abstractmethod
# def new_progress(self):
# """Create an appropriate subtype of Progress."""
# pass # pragma: no cover
class NullFrontend(Frontend):
"""A frontend that doesn't do anything."""
def __init__(self):
"""Construct a null frontend."""
super(NullFrontend, self).__init__()
def partial_info(self, data):
"""Part of a log message."""
pass
def partial_error(self, data):
"""Part of an error message."""
pass
def info(self, message):
"""Log an info-level message."""
pass
def error(self, message):
"""Log an error-level message."""
pass
_singleton_null_frontend = None
def _null_frontend():
global _singleton_null_frontend
if _singleton_null_frontend is None:
_singleton_null_frontend = NullFrontend()
return _singleton_null_frontend
class _ErrorRecordingFrontendProxy(Frontend):
def __init__(self, underlying):
super(_ErrorRecordingFrontendProxy, self).__init__()
self._errors = []
self.underlying = underlying
def info(self, message):
"""Log an info-level message."""
self.underlying.info(message)
def error(self, message):
"""Log an error-level message."""
self._errors.append(message)
self.underlying.error(message)
def pop_errors(self):
result = self._errors
self._errors = []
return result
def _new_error_recorder(frontend):
return _ErrorRecordingFrontendProxy(frontend)