From 898bc7c347498f4f7dda1e804f728ad7fe9c2758 Mon Sep 17 00:00:00 2001 From: Brendan Taylor <bct@diffeq.com> Date: Fri, 9 Jan 2009 19:55:26 +0000 Subject: [PATCH] gave latex processing its own file, merged duplicate processing and detection code --- src/common/exceptions.py | 2 +- src/common/gajim.py | 60 +------------- src/common/latex.py | 148 +++++++++++++++++++++++++++++++++++ src/conversation_textview.py | 95 +--------------------- 4 files changed, 153 insertions(+), 152 deletions(-) create mode 100644 src/common/latex.py diff --git a/src/common/exceptions.py b/src/common/exceptions.py index f91f600a39..9f20e1d977 100644 --- a/src/common/exceptions.py +++ b/src/common/exceptions.py @@ -83,7 +83,7 @@ class Cancelled(Exception): pass class LatexError(Exception): - '''sqlite2 raised pysqlite2.dbapi2.OperationalError''' + '''LaTeX processing failed for some reason''' def __init__(self, text=''): Exception.__init__(self) self.text = text diff --git a/src/common/gajim.py b/src/common/gajim.py index e5a6114708..89a72be325 100644 --- a/src/common/gajim.py +++ b/src/common/gajim.py @@ -176,64 +176,8 @@ else: if system('gpg -h >/dev/null 2>&1'): HAVE_GPG = False -import os -import random -from tempfile import gettempdir -from subprocess import Popen - -def check_for_latex_support(): - '''check is latex is available and if it can create a picture.''' - - exitcode = 0 - random.seed() - tmpfile = os.path.join(gettempdir(), "gajimtex_" + \ - random.randint(0,100).__str__()) - - # build latex string - texstr = '\\documentclass[12pt]{article}\\usepackage[dvips]{graphicx}' - texstr += '\\usepackage{amsmath}\\usepackage{amssymb}\\pagestyle{empty}' - texstr += '\\begin{document}\\begin{large}\\begin{gather*}test' - texstr += '\\end{gather*}\\end{large}\\end{document}' - - file_ = open(os.path.join(tmpfile + ".tex"), "w+") - file_.write(texstr) - file_.flush() - file_.close() - try: - if os.name == 'nt': - # CREATE_NO_WINDOW - p = Popen(['latex', '--interaction=nonstopmode', tmpfile + '.tex'], - creationflags=0x08000000, cwd=gettempdir()) - else: - p = Popen(['latex', '--interaction=nonstopmode', tmpfile + '.tex'], - cwd=gettempdir()) - exitcode = p.wait() - except Exception: - exitcode = 1 - if exitcode == 0: - try: - if os.name == 'nt': - # CREATE_NO_WINDOW - p = Popen(['dvipng', '-bg', 'white', '-T', 'tight', - tmpfile + '.dvi', '-o', tmpfile + '.png'], - creationflags=0x08000000, cwd=gettempdir()) - else: - p = Popen(['dvipng', '-bg', 'white', '-T', 'tight', - tmpfile + '.dvi', '-o', tmpfile + '.png'], cwd=gettempdir()) - exitcode = p.wait() - except Exception: - exitcode = 1 - extensions = ['.tex', '.log', '.aux', '.dvi', '.png'] - for ext in extensions: - try: - os.remove(tmpfile + ext) - except Exception: - pass - if exitcode == 0: - return True - return False - -HAVE_LATEX = check_for_latex_support() +import latex +HAVE_LATEX = latex.check_for_latex_support() gajim_identity = {'type': 'pc', 'category': 'client', 'name': 'Gajim'} gajim_common_features = [xmpp.NS_BYTESTREAM, xmpp.NS_SI, xmpp.NS_FILE, diff --git a/src/common/latex.py b/src/common/latex.py new file mode 100644 index 0000000000..fb1a57799d --- /dev/null +++ b/src/common/latex.py @@ -0,0 +1,148 @@ +# -*- coding:utf-8 -*- +## src/common/latex.py +## +## Copyright (C) 2005 Norman Rasmussen <norman AT rasmussen.co.za> +## Copyright (C) 2005-2006 Alex Mauer <hawke AT hawkesnest.net> +## Travis Shirk <travis AT pobox.com> +## Copyright (C) 2005-2007 Nikos Kouremenos <kourem AT gmail.com> +## Copyright (C) 2005-2008 Yann Leboulanger <asterix AT lagaule.org> +## Copyright (C) 2006 Dimitur Kirov <dkirov AT gmail.com> +## Copyright (C) 2006-2008 Jean-Marie Traissard <jim AT lapin.org> +## Copyright (C) 2008 Jonathan Schleifer <js-gajim AT webkeks.org> +## Julien Pivotto <roidelapluie AT gmail.com> +## Stephan Erb <steve-e AT h3c.de> +## +## This file is part of Gajim. +## +## Gajim 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; version 3 only. +## +## Gajim 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 Gajim. If not, see <http://www.gnu.org/licenses/>. +## + +import os +import random +from tempfile import gettempdir +from subprocess import Popen + +import gajim +from exceptions import LatexError + +# some latex commands are really bad +blacklist = ['\\def', '\\let', '\\futurelet', + '\\newcommand', '\\renewcomment', '\\else', '\\fi', '\\write', + '\\input', '\\include', '\\chardef', '\\catcode', '\\makeatletter', + '\\noexpand', '\\toksdef', '\\every', '\\errhelp', '\\errorstopmode', + '\\scrollmode', '\\nonstopmode', '\\batchmode', '\\read', '\\csname', + '\\newhelp', '\\relax', '\\afterground', '\\afterassignment', + '\\expandafter', '\\noexpand', '\\special', '\\command', '\\loop', + '\\repeat', '\\toks', '\\output', '\\line', '\\mathcode', '\\name', + '\\item', '\\section', '\\mbox', '\\DeclareRobustCommand', '\\[', + '\\]'] +# True if the string matches the blacklist +def check_blacklist(str_): + for word in blacklist: + if word in str_: + return True + return False + +def get_tmpfile_name(): + random.seed() + int_ = random.randint(0, 100) + return os.path.join(gettempdir(), 'gajimtex_' + int_.__str__()) + +def write_latex(filename, str_): + texstr = '\\documentclass[12pt]{article}\\usepackage[dvips]{graphicx}' + texstr += '\\usepackage{amsmath}\\usepackage{amssymb}' + texstr += '\\pagestyle{empty}' + texstr += '\\begin{document}\\begin{large}\\begin{gather*}' + texstr += str_ + texstr += '\\end{gather*}\\end{large}\\end{document}' + + file_ = open(filename, "w+") + file_.write(texstr) + file_.flush() + file_.close() + +# a wrapper for Popen so that no window gets opened on Windows +def popen_nt_friendly(command): + if os.name == 'nt': + # CREATE_NO_WINDOW + return Popen(command, creationflags=0x08000000, cwd=gettempdir()) + else: + return Popen(command, cwd=gettempdir()) + +def check_for_latex_support(): + '''check is latex is available and if it can create a picture.''' + + try: + filename = latex_to_image("test") + if filename: + # we have a file, conversion succeeded + os.remove(filename) + return True + return False + except LatexError: + return False + +def latex_to_image(str_): + result = None + exitcode = 0 + + # filter latex code with bad commands + if check_blacklist(str_): + # we triggered the blacklist, immediately return None + return None + + tmpfile = get_tmpfile_name() + + # build latex string + write_latex(os.path.join(tmpfile + '.tex'), str_) + + # convert TeX to dvi + try: + p = popen_nt_friendly(['latex', '--interaction=nonstopmode', + tmpfile + '.tex']) + exitcode = p.wait() + except Exception, e: + exitcode = _('Error executing "%(command)s": %(error)s') % { + 'command': 'latex --interaction=nonstopmode %s.tex' % tmpfile, + 'error': str(e)} + + if exitcode == 0: + # convert dvi to png + latex_png_dpi = gajim.config.get('latex_png_dpi') + try: + p = popen_nt_friendly(['dvipng', '-bg', 'rgb 1.0 1.0 1.0', '-T', + 'tight', '-D', latex_png_dpi, tmpfile + '.dvi', '-o', + tmpfile + '.png']) + exitcode = p.wait() + except Exception, e: + exitcode = _('Error executing "%(command)s": %(error)s') % { + 'command': 'dvipng -bg rgb 1.0 1.0 1.0 -T tight -D %s %s.dvi -o ' + '%s.png' % (latex_png_dpi, tmpfile, tmpfile), 'error': str(e)} + + # remove temp files created by us and TeX + extensions = ['.tex', '.log', '.aux', '.dvi'] + for ext in extensions: + try: + os.remove(tmpfile + ext) + except Exception: + pass + + if isinstance(exitcode, (unicode, str)): + raise LatexError(exitcode) + + if exitcode == 0: + result = tmpfile + '.png' + + return result + +# vim: se ts=3: diff --git a/src/conversation_textview.py b/src/conversation_textview.py index 227d7ff0e9..95c0fa7189 100644 --- a/src/conversation_textview.py +++ b/src/conversation_textview.py @@ -27,9 +27,6 @@ ## along with Gajim. If not, see <http://www.gnu.org/licenses/>. ## -import random -from tempfile import gettempdir -from subprocess import Popen from threading import Timer # for smooth scrolling import gtk @@ -45,6 +42,7 @@ import Queue import gtkgui_helpers from common import gajim from common import helpers +from common import latex from calendar import timegm from common.fuzzyclock import FuzzyClock @@ -959,95 +957,6 @@ class ConversationTextview: return index # the position after *last* special text - def latex_to_image(self, str_): - result = None - exitcode = 0 - - # some latex commands are really bad - blacklist = ['\\def', '\\let', '\\futurelet', - '\\newcommand', '\\renewcomment', '\\else', '\\fi', '\\write', - '\\input', '\\include', '\\chardef', '\\catcode', '\\makeatletter', - '\\noexpand', '\\toksdef', '\\every', '\\errhelp', '\\errorstopmode', - '\\scrollmode', '\\nonstopmode', '\\batchmode', '\\read', '\\csname', - '\\newhelp', '\\relax', '\\afterground', '\\afterassignment', - '\\expandafter', '\\noexpand', '\\special', '\\command', '\\loop', - '\\repeat', '\\toks', '\\output', '\\line', '\\mathcode', '\\name', - '\\item', '\\section', '\\mbox', '\\DeclareRobustCommand', '\\[', - '\\]'] - - str_ = str_[2:len(str_)-2] - - # filter latex code with bad commands - for word in blacklist: - if word in str_: - exitcode = 1 - break - - if exitcode == 0: - random.seed() - tmpfile = os.path.join(gettempdir(), 'gajimtex_' + random.randint(0, - 100).__str__()) - - # build latex string - texstr = '\\documentclass[12pt]{article}\\usepackage[dvips]{graphicx}' - texstr += '\\usepackage{amsmath}\\usepackage{amssymb}' - texstr += '\\pagestyle{empty}' - texstr += '\\begin{document}\\begin{large}\\begin{gather*}' - texstr += str_ - texstr += '\\end{gather*}\\end{large}\\end{document}' - - file_ = open(os.path.join(tmpfile + '.tex'), 'w+') - file_.write(texstr) - file_.flush() - file_.close() - - try: - if os.name == 'nt': - # CREATE_NO_WINDOW - p = Popen(['latex', '--interaction=nonstopmode', - tmpfile + '.tex'], creationflags=0x08000000, cwd=gettempdir()) - else: - p = Popen(['latex', '--interaction=nonstopmode', - tmpfile + '.tex'], cwd=gettempdir()) - exitcode = p.wait() - except Exception, e: - exitcode = _('Error executing "%(command)s": %(error)s') % { - 'command': 'latex --interaction=nonstopmode %s.tex' % tmpfile, - 'error': str(e)} - - if exitcode == 0: - latex_png_dpi = gajim.config.get('latex_png_dpi') - try: - if os.name == 'nt': - # CREATE_NO_WINDOW - p = Popen(['dvipng', '-bg', 'rgb 1.0 1.0 1.0', '-T', 'tight', - '-D', latex_png_dpi, tmpfile + '.dvi', '-o', - tmpfile + '.png'], creationflags=0x08000000, cwd=gettempdir()) - else: - p = Popen(['dvipng', '-bg', 'rgb 1.0 1.0 1.0', '-T', 'tight', - '-D', latex_png_dpi, tmpfile + '.dvi', '-o', - tmpfile + '.png'], cwd=gettempdir()) - exitcode = p.wait() - except Exception, e: - exitcode = _('Error executing "%(command)s": %(error)s') % { - 'command': 'dvipng -bg rgb 1.0 1.0 1.0 -T tight -D %s %s.dvi -o ' - '%s.png' % (latex_png_dpi, tmpfile, tmpfile), 'error': str(e)} - - extensions = ['.tex', '.log', '.aux', '.dvi'] - for ext in extensions: - try: - os.remove(tmpfile + ext) - except Exception: - pass - - if isinstance(exitcode, (unicode, str)): - raise LatexError(exitcode) - - if exitcode == 0: - result = tmpfile + '.png' - - return result - def print_special_text(self, special_text, other_tags): '''is called by detect_and_print_special_text and prints special text (emots, links, formatting)''' @@ -1144,7 +1053,7 @@ class ConversationTextview: elif gajim.HAVE_LATEX and special_text.startswith('$$') and \ special_text.endswith('$$'): try: - imagepath = self.latex_to_image(special_text) + imagepath = latex.latex_to_image(special_text[2:-2]) except LatexError, e: # print the error after the line has been written gobject.idle_add(self.print_conversation_line, str(e), '', 'info', -- GitLab