This file is indexed.

/usr/lib/python3/dist-packages/gleetex/convenience.py is in python3-gleetex 2.3.1-1.

This file is owned by root:root, with mode 0o644.

The actual contents of the file can be viewed below.

  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
 26
 27
 28
 29
 30
 31
 32
 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
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
"""In order to convert images only if they are not already cached, the cached
converter sacrifices customizability for convenience and provides a class
converting a formula directly to a png file."""

import concurrent.futures
import multiprocessing
import os
import subprocess

from . import caching, document, image
from .caching import normalize_formula

class ConversionException(Exception):
    """This exception is raised whenever a problem occurs during conversion.
    Example:
    c = ConversionException("cause", "\\tau", 10, 38, 5)
    assert c.cause == cause
    assert c.formula == '\\tau'
    assert c.src_line_number == 10 # line number in source document (counting from 1)
    assert c.src_pos_on_line == 38 # position of formula in source line, counting from 1
    assert c.formula_count == 5 # fifth formula in document (starting from 1)
    """
    # mind your own business:
    #pylint: disable=too-many-arguments
    def __init__(self, cause, formula, src_line_number, src_pos_on_line, formula_count):
        # provide a default error message
        super().__init__("LaTeX failed at formula line {}, {}, no. {}: {}".format(
            src_line_number, src_pos_on_line, formula_count, cause))
        # provide attributes for upper level error handling
        self.cause = cause
        self.formula = formula
        self.src_line_number = src_line_number
        self.src_pos_on_line = src_pos_on_line
        self.formula_count = formula_count

class CachedConverter:
    """Convert formulas to images.

    c = CachedConverter(base_path)
    for formula in [... formulas ...]:
        pos, file_path = c.convert(formula)
        ...

    The formula is either converted  or retrieved from a cache in the same
    directory like the images.

    :param base_path directory to place files in (relative to the file
            converted. So if the file being converted is foo/bar.htex and the
            base_path is set to img, the image will be placed in foo/img/.
    :param keep_old_cache If an existing cache cannot be read (incompatible
        GladTeX version, ...) Aand the flag is set, the program will simply
        crash and tell the user to remove the cache (default). If set to False,
        the program will instead remove the cache and all eqn* files and
        recreate the cache.
    :param encoding The encoding for the LaTeX document, default None
    """
    GLADTEX_CACHE_FILE_NAME = 'gladtex.cache'
    _converter = image.Tex2img # can be statically altered for testing purposes

    def __init__(self, base_path, keep_old_cache=True, encoding=None):
        if base_path and not os.path.exists(base_path):
            os.makedirs(base_path)
        cache_path = os.path.join(base_path,
                CachedConverter.GLADTEX_CACHE_FILE_NAME)
        self.__cache = caching.ImageCache(cache_path,
                keep_old_cache=keep_old_cache)
        self.__options = {'dpi' : None, 'transparency' : None,
                'background_color' : None, 'foreground_color' : None,
                'preamble' : None, 'latex_maths_env' : None,
                'keep_latex_source': False}
        self.__encoding = encoding
        self.__replace_nonascii = False


    def set_option(self, option, value):
        """Set one of the options accepted for gleetex.image.Tex2img. `option`
        must be one of dpi, transparency, background_color, foreground_color,
        preamble, latex_maths_env, keep_latex_source."""
        if not option in self.__options.keys():
            raise ValueError("Option must be one of " + \
                    ', '.join(self.__options.keys()))
        self.__options[option] = value

    def set_replace_nonascii(self, flag):
        """If set, GladTeX will convert all non-ascii character to LaTeX
        commands. This setting is passed through to document.LaTeXDocument."""
        self.__replace_nonascii = flag


    def convert_all(self, base_path, formulas):
        """convert_all(formulas)
        Convert all formulas using self.convert concurrently. Each element of
        `formulas` must be a tuple containing (formula, displaymath,
        Formulas already contained in the cache are not converted.
        """
        formulas_to_convert = self._get_formulas_to_convert(base_path, formulas)
        self._convert_concurrently(formulas_to_convert)

    def _get_formulas_to_convert(self, base_path, formulas):
        """Return a list of formulas to convert, along with their count in the
        global list of formulas of the document being converted and the file
        name. Function was decomposed for better testability."""
        formulas_to_convert = [] # find as many file names as equations
        eqn_path = lambda x: os.path.join(base_path, 'eqn%03d.png' % x)

        # is (formula, display_math) already in the list of formulas to convert;
        # displaymath is important since formulas look different in inline maths
        formula_was_converted = lambda f, dsp: (normalize_formula(f), dsp) in \
                ((normalize_formula(u[0]), u[3]) for u in formulas_to_convert)
        # find enough free file names
        file_name_count = 0
        used_file_names = [] # track which file names have been assigned
        for formula_count, (pos, dsp, formula) in enumerate(formulas):
            if not self.__cache.contains(formula, dsp) and \
                    not formula_was_converted(formula, dsp):
                while os.path.exists(eqn_path(file_name_count)) or \
                    eqn_path(file_name_count) in used_file_names:
                    file_name_count += 1
                used_file_names.append(eqn_path(file_name_count))
                formulas_to_convert.append((formula, pos, eqn_path(file_name_count),
                    dsp, formula_count + 1))
        return formulas_to_convert


    def _convert_concurrently(self, formulas_to_convert):
        """The actual concurrent conversion process. Method is intended to be
        called from convert_all()."""
        # use roughly 2,5 * number of processors as amount of threads (I/O
        # bound); but don't overdo it with fivetimes like the thread pool does
        # it (gladtex might be in turn run in parallel on a machine)
        thread_count = int(multiprocessing.cpu_count() * 2.5)
        # convert missing formulas
        with concurrent.futures.ThreadPoolExecutor(max_workers=thread_count) as executor:
            # start conversion and mark each thread with its formula, position
            # in the source file and formula_count (index into a global list of
            # formulas)
            jobs = {executor.submit(self.convert, eqn, path, dsp): (eqn, pos, count)
                for (eqn, pos, path, dsp, count) in formulas_to_convert}
            error_occurred = None
            for future in concurrent.futures.as_completed(jobs):
                if error_occurred and not future.done():
                    future.cancel()
                    continue
                formula, pos_in_src, formula_count = jobs[future]
                try:
                    data = future.result()
                except subprocess.SubprocessError as e:
                    if 'inputenc Error' in e.args[0]:
                        print("piep")
                    # retrieve the position (line, pos on line) in the source
                    # document from original formula list
                    pos_in_src = list(p+1 for p in pos_in_src) # user expects lines/pos_in_src' to count from 1
                    self.__cache.write() # write back cache with valid entries
                    error_occurred = ConversionException(str(e.args[0]), formula,
                            pos_in_src[0], pos_in_src[1], formula_count)
                else:
                    self.__cache.add_formula(formula, data['pos'], data['path'],
                            data['displaymath'])
                    self.__cache.write()
            #pylint: disable=raising-bad-type
            if error_occurred:
                raise error_occurred



    def convert(self, formula, output_path, displaymath=False):
        """convert(formula, output_path, displaymath=False)
        Convert given formula with displaymath/inlinemath.
        This method wraps the formula in a tex document, executes all the steps
        to produce a PNG file and return the positioning information as given by
        dvipng.
        :param formula formula to convert
        :param output_path image output path
        :param displaymath whether or not to use displaymath during the conversion
        :return dictionary with position (pos), image path (path) and formula
            style (displaymath, boolean) as a dictionary with the keys in
            parenthesis
        """
        latex = document.LaTeXDocument(formula)
        latex.set_displaymath(displaymath)
        if self.__options['preamble']: # add preamble to LaTeX document
            latex.set_preamble_string(self.__options['preamble'])
        if self.__options['latex_maths_env']:
            latex.set_latex_environment(self.__options['latex_maths_env'])
        if self.__encoding:
            latex.set_encoding(self.__encoding)
        if self.__replace_nonascii:
            latex.set_replace_nonascii(True)
        try:
            latex_str = str(latex)
        except ValueError as e: # propagate error
            raise ConversionException(e.args[0], formula, 0, 0, 0)
        conv = self._converter(latex_str, output_path)
        # apply configured image output options
        for option, value in self.__options.items():
            if value and hasattr(conv, 'set_' + option):
                getattr(conv, 'set_' + option)(value)
        conv.convert()
        pos = conv.get_positioning_info()
        return {'pos' : pos, 'path' : output_path, 'displaymath' :
            displaymath}

    def get_data_for(self, formula, display_math):
        """Simple wrapper around ImageCache."""
        return self.__cache.get_data_for(formula, display_math)