formats.py 3.58 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
# -*- coding: utf-8 -*-
#
# diffoscope: in-depth comparison of files, archives, and directories
#
# Copyright © 2016 Chris Lamb <lamby@debian.org>
#
# diffoscope is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# diffoscope is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with diffoscope.  If not, see <https://www.gnu.org/licenses/>.

import logging

from ..profiling import profile

from .text import TextPresenter
from .json import JSONPresenter
26
from .html import HTMLPresenter, HTMLDirectoryPresenter
27 28 29 30 31 32
from .markdown import MarkdownTextPresenter
from .restructuredtext import RestructuredTextPresenter

logger = logging.getLogger(__name__)


33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78
class PresenterManager(object):
    _singleton = {}

    def __init__(self):
        self.__dict__ = self._singleton

        if not self._singleton:
            self.reset()

    def reset(self):
        self.config = {}

    def configure(self, parsed_args):
        FORMATS = {
            'text': {
                'klass': TextPresenter,
                'target': parsed_args.text_output,
            },
            'html': {
                'klass': HTMLPresenter,
                'target': parsed_args.html_output,
            },
            'json': {
                'klass': JSONPresenter,
                'target': parsed_args.json_output,
            },
            'markdown': {
                'klass': MarkdownTextPresenter,
                'target': parsed_args.markdown_output,
            },
            'restructuredtext': {
                'klass': RestructuredTextPresenter,
                'target': parsed_args.restructuredtext_output,
            },
            'html_directory': {
                'klass': HTMLDirectoryPresenter,
                'target': parsed_args.html_output_directory,
            },
        }

        self.config = {
            k: v for k, v in FORMATS.items() if v['target'] is not None
        }

        # If no output specified, default to printing --text output to stdout
        if not self.config:
79
            FORMATS['text']['target'] = '-'
80 81 82 83 84 85 86 87
            self.config['text'] = FORMATS['text']

        logger.debug(
            "Will generate the following formats: %s",
            ", ".join(self.config.keys()),
        )

    def output(self, difference, parsed_args, has_differences):
88 89 90
        if difference is None:
            return

91 92 93
        for name, data in self.config.items():
            logger.debug("Generating %r output at %r", name, data['target'])

94 95 96 97 98 99 100 101 102
            # As a special case for text format, write an empty file instead of
            # an empty diff (with headers including the path). This lets people
            # test if the file is empty.
            if not has_differences and name == 'text':
                target = data['target']
                if target != '-':
                    open(target, 'w').close()
                continue

103
            with profile('output', name):
104
                data['klass'].run(data, difference, parsed_args)
105 106 107 108 109 110 111

    def compute_visual_diffs(self):
        """
        Don't waste time computing visual differences if we won't use them.
        """

        return any(
112
            x['klass'].supports_visual_diffs for x in self.config.values()
113
        )