From ad770f4b4d956f4d0915aca2db28c9a00879bb64 Mon Sep 17 00:00:00 2001 From: Greg Hamerly Date: Fri, 3 Jan 2020 17:42:56 -0600 Subject: [PATCH 1/3] remove cgi, which seems to be causing problems Fixes #162 cgi.escape() would cause "<" to become "<", which would then get rendered by plasTeX as "&lt;". Removing cgi.escape() fixes the issue. One other change rolled into this commit is a necessary change to listingsutf8.py to read input files properly. --- problemtools/ProblemPlasTeX/ProblemsetMacros.py | 9 +++------ problemtools/ProblemPlasTeX/listingsutf8.py | 5 +---- 2 files changed, 4 insertions(+), 10 deletions(-) diff --git a/problemtools/ProblemPlasTeX/ProblemsetMacros.py b/problemtools/ProblemPlasTeX/ProblemsetMacros.py index fadd4a3b..ecc54208 100644 --- a/problemtools/ProblemPlasTeX/ProblemsetMacros.py +++ b/problemtools/ProblemPlasTeX/ProblemsetMacros.py @@ -2,7 +2,6 @@ import os import os.path import codecs -import cgi from plasTeX.DOM import Node from plasTeX.Base import Command from plasTeX.Base import DimenCommand @@ -46,9 +45,7 @@ class sampletable(Command): args = 'header1 file1:str header2 file2:str' def read_sample_file(self, filename): - data = open(filename, 'rb').read().decode('utf8') - data = cgi.escape(data) - return data + return open(filename, 'rb').read().decode('utf8') def invoke(self, tex): res = Command.invoke(self, tex) @@ -82,12 +79,12 @@ def read_sample_interaction(self, filename): line = line[1:] if mode != cur_mode: if cur_mode: messages.append({'mode': cur_mode, - 'data': cgi.escape('\n'.join(cur_msg))}) + 'data': '\n'.join(cur_msg)}) cur_msg = [] cur_msg.append(line) cur_mode = mode if cur_mode: messages.append({'mode': cur_mode, - 'data': cgi.escape('\n'.join(cur_msg))}) + 'data': '\n'.join(cur_msg)}) return messages def invoke(self, tex): diff --git a/problemtools/ProblemPlasTeX/listingsutf8.py b/problemtools/ProblemPlasTeX/listingsutf8.py index da3d4cee..d9bc21e1 100644 --- a/problemtools/ProblemPlasTeX/listingsutf8.py +++ b/problemtools/ProblemPlasTeX/listingsutf8.py @@ -1,7 +1,6 @@ from plasTeX.Base import Command from plasTeX.Logging import getLogger -import cgi import os log = getLogger() @@ -13,9 +12,7 @@ class lstinputlisting(Command): args = '* [ options:dict ] file:str' def read_file(self, filename): - data = open(filename, 'r').read().decode('utf8') - data = cgi.escape(data) - return data + return open(filename, 'rb').read().decode('utf8') def invoke(self, tex): res = Command.invoke(self, tex) From 2ccd7131f48a79a75b7a548bad94d4af3be85e9d Mon Sep 17 00:00:00 2001 From: Greg Hamerly Date: Mon, 6 Jan 2020 07:56:43 -0600 Subject: [PATCH 2/3] use cgi.escape for python2 (i.e. plastex1) only I.e. do not use any escaping for python3/plastex2 Also, use io.open with encoding=utf-8 rather than using decode('utf-8') --- .../ProblemPlasTeX/ProblemsetMacros.py | 20 ++++++++++++++----- problemtools/ProblemPlasTeX/listingsutf8.py | 7 ++++++- 2 files changed, 21 insertions(+), 6 deletions(-) diff --git a/problemtools/ProblemPlasTeX/ProblemsetMacros.py b/problemtools/ProblemPlasTeX/ProblemsetMacros.py index ecc54208..1079d605 100644 --- a/problemtools/ProblemPlasTeX/ProblemsetMacros.py +++ b/problemtools/ProblemPlasTeX/ProblemsetMacros.py @@ -1,13 +1,21 @@ import sys import os import os.path -import codecs +import io from plasTeX.DOM import Node from plasTeX.Base import Command from plasTeX.Base import DimenCommand from plasTeX.Logging import getLogger import plasTeX.Packages.graphics as graphics +if sys.version_info.major == 2: + import cgi + def plastex_escape(s): + return cgi.escape(s) +else: + def plastex_escape(s): + return s + log = getLogger() status = getLogger('status') @@ -45,7 +53,9 @@ class sampletable(Command): args = 'header1 file1:str header2 file2:str' def read_sample_file(self, filename): - return open(filename, 'rb').read().decode('utf8') + data = io.open(filename, 'r', encoding='utf-8').read() + data = plastex_escape(data) + return data def invoke(self, tex): res = Command.invoke(self, tex) @@ -67,7 +77,7 @@ class sampletableinteractive(Command): args = 'header read write file:str' def read_sample_interaction(self, filename): - data = open(filename, 'rb').read().decode('utf8') + data = io.open(filename, 'r', encoding='utf-8').read() messages = [] cur_msg = [] cur_mode = None @@ -79,12 +89,12 @@ def read_sample_interaction(self, filename): line = line[1:] if mode != cur_mode: if cur_mode: messages.append({'mode': cur_mode, - 'data': '\n'.join(cur_msg)}) + 'data': plastex_escape('\n'.join(cur_msg))}) cur_msg = [] cur_msg.append(line) cur_mode = mode if cur_mode: messages.append({'mode': cur_mode, - 'data': '\n'.join(cur_msg)}) + 'data': plastex_escape('\n'.join(cur_msg))}) return messages def invoke(self, tex): diff --git a/problemtools/ProblemPlasTeX/listingsutf8.py b/problemtools/ProblemPlasTeX/listingsutf8.py index d9bc21e1..2a2d1f56 100644 --- a/problemtools/ProblemPlasTeX/listingsutf8.py +++ b/problemtools/ProblemPlasTeX/listingsutf8.py @@ -2,6 +2,9 @@ from plasTeX.Logging import getLogger import os +import io + +import ProblemsetMacros log = getLogger() @@ -12,7 +15,9 @@ class lstinputlisting(Command): args = '* [ options:dict ] file:str' def read_file(self, filename): - return open(filename, 'rb').read().decode('utf8') + data = io.open(filename, 'r', encoding='utf-8').read() + data = ProblemsetMacros.plastex_escape(data) + return data def invoke(self, tex): res = Command.invoke(self, tex) From e94d3a67e2402bcbcb2269827851ca53842eb2e1 Mon Sep 17 00:00:00 2001 From: Greg Hamerly Date: Mon, 6 Jan 2020 19:45:17 -0600 Subject: [PATCH 3/3] change file() to open() --- problemtools/verifyproblem.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/problemtools/verifyproblem.py b/problemtools/verifyproblem.py index c3a8b3af..4be46423 100644 --- a/problemtools/verifyproblem.py +++ b/problemtools/verifyproblem.py @@ -300,7 +300,8 @@ def __init__(self, problem, datadir, parent=None): configfile = os.path.join(self._datadir, 'testdata.yaml') if os.path.isfile(configfile): try: - self.config = yaml.safe_load(file(configfile)) + with open(configfile) as f: + self.config = yaml.safe_load(f) except Exception as e: self.error(e) self.config = {}