Esempio n. 1
0
    def _get_feed_data_dir(self):
        d = os.path.join(self._framework.plugins['vars'].vars['intermediate_data_dir'], "StillWeb.FeedGenerator")

        # Quietly make sure the directory exists
        ensure_path(d)

        return d
Esempio n. 2
0
    def math_placeholder(self, latex_code, force_img=False):
        # Strip whitespace
        latex_code = latex_code.strip()

        # If the code is empty, don't do anything.
        if not latex_code:
            raise ReplaceWithNothing()

        # Find the texvc executable
        texvc_program_dir = self._framework.plugins['vars'].vars['texvc_program_dir']

        # Find the output directory
        (output_dir_url, output_dir) = self._get_texvc_outdir()
        intermediate_dir = self._get_my_intermediate_dir()

        # Quietly make sure both directories exist
        ensure_path(output_dir)
        ensure_path(intermediate_dir)

        # Create a Texvc instance
        texvc = Texvc(texvc_program_dir, output_dir)

        # Two MD5 sums are calculated:
        #   1. The "original" checksum of the code actually found in the page
        #   2. The "canonical" checksum that texvc generates
        # These might be identical, or they might be different.  We cache them both.
        orig_md5 = hashlib.md5(latex_code.encode('UTF-8')).hexdigest()
        orig_md5_filename = os.path.join(intermediate_dir, "texvc-original-%s-sum" % (orig_md5,))

        # Try to read the canonical MD5 sum from the cache file.  Generate it if it's not cached.
        try:
            f = open(orig_md5_filename, "rt")
            canonical_md5 = binascii.b2a_hex(binascii.a2b_hex(f.read().strip().encode('ascii'))).decode('ascii')    # make sure it's hexadecimal
            assert len(canonical_md5) == 32     # 32 hexadecimal digits
            f.close()
        except EnvironmentError as exc:
            if exc.errno != errno.ENOENT:
                raise

            # Generate the MD5 sum of the *canonical* code (i.e. of texvc_tex's output)
            canonical_md5 = texvc.hash_code(latex_code).hexdigest()

            # Cache the generated MD5 sum for future reference
            f = open(orig_md5_filename, "wt", encoding="UTF-8")
            f.write(canonical_md5)
            f.close()

        # Check if we've already generated the output
        stamp_filename = os.path.join(intermediate_dir, "texvc-canonical-%s-stamp" % (canonical_md5,))
        result_filename = os.path.join(intermediate_dir, "texvc-canonical-%s-result" % (canonical_md5,))
        output_basename = "%s.png" % (canonical_md5,)
        output_filename = os.path.join(output_dir, output_basename)
        output_url = rfc3986_urljoin(output_dir_url, output_basename)
        if os.path.exists(stamp_filename) and os.path.exists(output_filename):
            print("skipping TeX %s" % (output_filename,))

            # Use the cached result
            result = pickle.load(open(result_filename, "rb"))

            # Check the hash result - this should never fail unless the cache file is corrupt
            if result['md5'] != canonical_md5:
                raise AssertionError("corrupt file: %r" % (result_filename,))

        else:
            print("generating TeX %s" % (output_filename,))

            # Parse texvc result and check for errors
            result = texvc.run_texvc(latex_code)

            # Check the hash result - our caching here breaks if we get this wrong.
            if result['md5'] != canonical_md5:
                raise AssertionError("texvc md5 sum mismatch (code=%r, my_md5=%r, texvc_md5=%r)" % (
                    latex_code, canonical_md5, result['md5']))

            # Check that the output file was created
            if not os.path.exists(output_filename):
                raise TexvcRuntimeError("texvc didn't create output file %r (canonical_md5=%r, code=%r)" % (output_filename, canonical_md5, latex_code))

            # Save the result for future use
            pickle.dump(result, open(result_filename, "wb"))

            # Write the canonical MD5 sum to the timestamp file (and update its timestamp)
            open(stamp_filename, "ab").close()
            os.utime(stamp_filename, None)     # should be unnecessary if we're writing to the file

        # If texvc gave us some HTML code (of moderate or conservative strictness), use that.
        if not force_img and result['html'] is not None and result['html_strictness'] > 0:
            raise ReplaceWithHTML(result['html'])

        # TODO - MathML support can go here if we want it.

        # Fall-back on the PNG image.
        imgElement = minidom.parseString("<img/>").documentElement
        imgElement.setAttribute('class', 'tex')
        imgElement.setAttribute('src', output_url)
        imgElement.setAttribute('alt', latex_code)
        raise ReplaceWithNode(imgElement)