From 0e4eb9bff3763d3372f23b27f9c2390705e2d962 Mon Sep 17 00:00:00 2001 From: Jakub Stasiak Date: Fri, 7 Feb 2020 12:59:24 +0100 Subject: Fix "AttributeError: module 'cgi' has no attribute 'escape'" on Python 3.8 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Full error: % screenplain Big-Fish.fountain Big-Fish.html Traceback (most recent call last): File "/Users/user/.ve38/bin/screenplain", line 6, in main(sys.argv[1:]) File "/Users/user/.ve38/lib/python3.8/site-packages/screenplain/main.py", line 125, in main convert( File "/Users/user/.ve38/lib/python3.8/site-packages/screenplain/export/html.py", line 183, in convert convert_full( File "/Users/user/.ve38/lib/python3.8/site-packages/screenplain/export/html.py", line 210, in convert_full convert_bare(screenplay, out) File "/Users/user/.ve38/lib/python3.8/site-packages/screenplain/export/html.py", line 225, in convert_bare formatter.convert(screenplay) File "/Users/user/.ve38/lib/python3.8/site-packages/screenplain/export/html.py", line 99, in convert format_function(para) File "/Users/user/.ve38/lib/python3.8/site-packages/screenplain/export/html.py", line 153, in format_action self.out.write(to_html(line)) File "/Users/user/.ve38/lib/python3.8/site-packages/screenplain/export/html.py", line 60, in to_html html = text.to_html() File "/Users/user/.ve38/lib/python3.8/site-packages/screenplain/richstring.py", line 62, in to_html html = ''.join(seg.to_html() for seg in self.segments) File "/Users/user/.ve38/lib/python3.8/site-packages/screenplain/richstring.py", line 62, in html = ''.join(seg.to_html() for seg in self.segments) File "/Users/user/.ve38/lib/python3.8/site-packages/screenplain/richstring.py", line 136, in to_html _escape(self.text), File "/Users/user/.ve38/lib/python3.8/site-packages/screenplain/richstring.py", line 17, in _escape encoded = cgi.escape(s).encode('ascii', 'xmlcharrefreplace') AttributeError: module 'cgi' has no attribute 'escape' cgi.escape() is gone in Python 3.8, html.escape() should be used instead. Since html.escape() defaults to quote=True, we need to explicitly disable escaping quotation marks to keep doing the same thing. A question arises though – should quotation marks be actually kept verbatim here or was it unintentional? --- screenplain/richstring.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/screenplain/richstring.py b/screenplain/richstring.py index ad667d1..1859e12 100644 --- a/screenplain/richstring.py +++ b/screenplain/richstring.py @@ -3,9 +3,13 @@ # http://www.opensource.org/licenses/mit-license.php import re -import cgi import six +try: + from html import escape as html_escape +except ImportError: + from cgi import escape as html_escape + _magic_re = re.compile(u'[\ue700-\ue705]') @@ -14,7 +18,7 @@ def _escape(s): and non-ascii characters with ampersand escapes. """ - encoded = cgi.escape(s).encode('ascii', 'xmlcharrefreplace') + encoded = html_escape(s, quote=False).encode('ascii', 'xmlcharrefreplace') # In Py3, encoded is bytes type, so convert it to a string return encoded.decode('ascii') -- cgit From e946ac7cdb4e61458502da629d79d78cac22d060 Mon Sep 17 00:00:00 2001 From: Jakub Stasiak Date: Sat, 8 Feb 2020 13:52:06 +0100 Subject: Fix "TypeError: write() argument must be str, not bytes" on Python 3 This used to happen when writing to stdout. On Python 3 stdout is an instance of TextIOWrapper which is a text-based interface. It wraps a bytes-based writer though which is accessible through the buffer attribute, so let's use that to either write to it directly or to get an encoding writer. Fixes https://github.com/vilcans/screenplain/issues/53. --- screenplain/main.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/screenplain/main.py b/screenplain/main.py index 770427c..313498f 100644 --- a/screenplain/main.py +++ b/screenplain/main.py @@ -109,9 +109,9 @@ def main(args): output = open(output_file, 'wb') else: if output_encoding: - output = codecs.getwriter(output_encoding)(sys.stdout) + output = codecs.getwriter(output_encoding)(sys.stdout.buffer) else: - output = sys.stdout + output = sys.stdout.buffer try: if format == 'text': -- cgit