# # Copyright (c) 2010 Testrepository Contributors # # Licensed under either the Apache License, Version 2.0 or the BSD 3-clause # license at the users choice. A copy of both licenses are available in the # project source as Apache-2.0 and BSD. You may not use this file except in # compliance with one of these two licences. # # Unless required by applicable law or agreed to in writing, software # distributed under these licenses is distributed on an "AS IS" BASIS, WITHOUT # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # license you chose for the specific language governing permissions and # limitations under that license. """A decorator for UIs to allow use of additional command objects in-process.""" from io import BytesIO import optparse from testrepository import ui class UI(ui.AbstractUI): """A decorating UI. Not comprehensive yet - only supports overriding input streams. Note that because UI objects carry command specific state only specific things can be delegated - option/argument lookup, streams. set_command for instance, does not get passed to the decorated UI unless it has not been initialised. """ def __init__(self, input_streams=None, options={}, decorated=None): """Create a decorating UI. :param input_streams: The input steams to present from this UI. Should be a list of (stream name, file) tuples. :param options: Dict of options to replace in the base UI. These are merged with the underlying ones when set_command is called. :param decorated: The UI to decorate. """ self._decorated = decorated self.input_streams = {} if input_streams: for stream_type, stream_value in input_streams: self.input_streams.setdefault(stream_type, []).append( stream_value) self._options = options @property def arguments(self): return self._decorated.arguments @property def here(self): return self._decorated.here def _iter_streams(self, stream_type): streams = self.input_streams.pop(stream_type, []) for stream_value in streams: if getattr(stream_value, 'read', None): yield stream_value else: yield BytesIO(stream_value) def make_result(self, get_id, test_command, previous_run=None): return self._decorated.make_result( get_id, test_command, previous_run=previous_run) def output_error(self, error_tuple): return self._decorated.output_error(error_tuple) def output_rest(self, rest_string): return self._decorated.output_rest(rest_string) def output_stream(self, stream): return self._decorated.output_stream(stream) def output_table(self, table): return self._decorated.output_table(table) def output_tests(self, tests): return self._decorated.output_tests(tests) def output_values(self, values): return self._decorated.output_values(values) def output_summary(self, successful, tests, tests_delta, time, time_delta, values): return self._decorated.output_summary( successful, tests, tests_delta, time, time_delta, values) def set_command(self, cmd): self.cmd = cmd result = True if getattr(self._decorated, 'cmd', None) is None: result = self._decorated.set_command(cmd) # Pickup the repository factory from the decorated UI's command. cmd.repository_factory = self._decorated.cmd.repository_factory # Merge options self.options = optparse.Values() for option in dir(self._decorated.options): if option.startswith('_'): continue setattr(self.options, option, getattr(self._decorated.options, option)) for option, value in self._options.items(): setattr(self.options, option, value) return result def subprocess_Popen(self, *args, **kwargs): return self._decorated.subprocess_Popen(*args, **kwargs)