Bug 1255876 - Overriding the diff chunk generator to take into account explicit per-extension overrides; r=glob draft
authorSalva
Thu, 05 May 2016 17:54:30 +0200
changeset 8058 fb31f549967d2f0ff443185071063f06e1c4d8d0
parent 8057 5ed1e407bfb14cb8dad8f1d15dc4e054eb1ef372
child 8059 f017cb7e92444b28caf3a80eeb8a61dc14290ddd
push id805
push usersalva@unoyunodiez.com
push dateThu, 05 May 2016 15:55:29 +0000
reviewersglob
bugs1255876
Bug 1255876 - Overriding the diff chunk generator to take into account explicit per-extension overrides; r=glob MozReview-Commit-ID: ImDLT2T4yMj
pylib/pygments_override/pygments_override/extension.py
pylib/pygments_override/pygments_override/overridable_chunk_generator.py
--- a/pylib/pygments_override/pygments_override/extension.py
+++ b/pylib/pygments_override/pygments_override/extension.py
@@ -1,11 +1,46 @@
+import logging
+
 from reviewboard.extensions.base import Extension
+from reviewboard.diffviewer.chunk_generator import (
+    get_diff_chunk_generator_class,
+    set_diff_chunk_generator_class
+)
+
+from pygments_override.overridable_chunk_generator import (
+    OverridableDiffChunkGenerator
+)
+
+
+logger = logging.getLogger(__name__)
+
 
 class PygmentsOverride(Extension):
     metadata = {
         'Name': 'pygments-override',
         'Summary': 'Customize Pygments for specific file extensions',
     }
 
+    default_settings = {'overrides': ''}
+
+    is_configurable = True
+
     def initialize(self):
-        # Your extension initialization is done here.
-        pass
+        self._original_chunk_generator_class = get_diff_chunk_generator_class()
+        set_diff_chunk_generator_class(OverridableDiffChunkGenerator)
+        logger.info('overridable diff chunk generator class set!')
+
+    def shutdown(self):
+        set_diff_chunk_generator_class(self._original_chunk_generator_class)
+        logger.info('original diff chunk generator class restored!')
+        super(PygmentsOverride, self).shutdown()
+
+    def get_overrides_map(self):
+        overrides = self.settings['overrides'].splitlines()
+        valid_overrides = [override for override in overrides
+                           if '=' in override]
+        if valid_overrides != overrides:
+            invalid_overrides = set(overrides) - set(valid_overrides)
+            formatted_list = '\n'.join(invalid_overrides)
+            logger.error('ignoring malformed overrides:\n%s ' % formatted_list)
+
+        return dict([override.split('=') for override in valid_overrides])
new file mode 100644
--- /dev/null
+++ b/pylib/pygments_override/pygments_override/overridable_chunk_generator.py
@@ -0,0 +1,57 @@
+import logging
+from os.path import splitext
+
+from pygments import highlight
+from pygments.lexers import guess_lexer_for_filename, get_lexer_by_name
+
+from reviewboard.extensions.base import get_extension_manager
+from reviewboard.diffviewer.diffutils import split_line_endings
+from reviewboard.diffviewer.chunk_generator import (
+    get_diff_chunk_generator_class,
+    NoWrapperHtmlFormatter
+)
+
+
+logger = logging.getLogger(__name__)
+
+DiffChunkGenerator = get_diff_chunk_generator_class()
+
+
+class OverridableDiffChunkGenerator(DiffChunkGenerator):
+    """A chunk generator which overrides syntax highlighting."""
+
+    def _apply_pygments(self, data, filename):
+        """Applies Pygments syntax-highlighting to a file's contents.
+
+        Syntax highlight obeys a explicitly provided list of preferences by
+        extension or it is derived from the contents of the file.
+
+        The resulting HTML will be returned as a list of lines.
+        """
+        lexer = self._get_preferred_lexer(
+            filename, stripln=False, encoding='utf-8')
+        logger.debug('preferred lexer for %s: %s' % (filename, lexer))
+        if not lexer:
+            lexer = guess_lexer_for_filename(
+                filename, data, stripnl=False,
+                encoding='utf-8')
+
+        lexer.add_filter('codetagify')
+
+        return split_line_endings(highlight(data, lexer,
+                                            NoWrapperHtmlFormatter()))
+
+    def _get_preferred_lexer(self, filename, **options):
+        ext = splitext(filename)[1]
+        lexername = get_overrides().get(ext, None)
+        try:
+            lexer = get_lexer_by_name(lexername, **options)
+        except:
+            lexer = None
+        return lexer
+
+
+def get_overrides():
+    extension = get_extension_manager().get_enabled_extension(
+        'pygments_override.extension.PygmentsOverride')
+    return extension.get_overrides_map()