From 4cd10b79e251008a3104d2054ed294a75641aa76 Mon Sep 17 00:00:00 2001 From: gdesmar <75089569+gdesmar@users.noreply.github.com> Date: Tue, 8 Oct 2024 13:48:39 +0000 Subject: [PATCH 1/3] Convert docstring from bytes to str --- uncompyle6/semantics/helper.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/uncompyle6/semantics/helper.py b/uncompyle6/semantics/helper.py index 27c21a0d..78998bec 100644 --- a/uncompyle6/semantics/helper.py +++ b/uncompyle6/semantics/helper.py @@ -152,6 +152,9 @@ def is_lambda_mode(compile_mode: str) -> bool: def print_docstring(self, indent, docstring): + if isinstance(docstring, bytes): + docstring = docstring.decode("utf8", errors="backslashreplace") + quote = '"""' if docstring.find(quote) >= 0: if docstring.find("'''") == -1: From 20d0a60550ec4ac63e4843d73a3ac4747dec285c Mon Sep 17 00:00:00 2001 From: gdesmar <75089569+gdesmar@users.noreply.github.com> Date: Thu, 10 Oct 2024 20:24:56 +0000 Subject: [PATCH 2/3] Remove duplicate code of print_docstring --- uncompyle6/semantics/n_actions.py | 67 +------------------------------ 1 file changed, 2 insertions(+), 65 deletions(-) diff --git a/uncompyle6/semantics/n_actions.py b/uncompyle6/semantics/n_actions.py index cdb6ffa9..a15d34fc 100644 --- a/uncompyle6/semantics/n_actions.py +++ b/uncompyle6/semantics/n_actions.py @@ -26,7 +26,7 @@ from uncompyle6.semantics.consts import ( PRECEDENCE, minint, ) -from uncompyle6.semantics.helper import find_code_node, flatten_list +from uncompyle6.semantics.helper import find_code_node, flatten_list, print_docstring from uncompyle6.util import better_repr, get_code_name @@ -541,70 +541,7 @@ class NonterminalActions: else: docstring = node[0].pattr - quote = '"""' - if docstring.find(quote) >= 0: - if docstring.find("'''") == -1: - quote = "'''" - - self.write(indent) - docstring = repr(docstring.expandtabs())[1:-1] - - for orig, replace in ( - ("\\\\", "\t"), - ("\\r\\n", "\n"), - ("\\n", "\n"), - ("\\r", "\n"), - ('\\"', '"'), - ("\\'", "'"), - ): - docstring = docstring.replace(orig, replace) - - # Do a raw string if there are backslashes but no other escaped characters: - # also check some edge cases - if ( - "\t" in docstring - and "\\" not in docstring - and len(docstring) >= 2 - and docstring[-1] != "\t" - and (docstring[-1] != '"' or docstring[-2] == "\t") - ): - self.write("r") # raw string - # Restore backslashes unescaped since raw - docstring = docstring.replace("\t", "\\") - else: - # Escape the last character if it is the same as the - # triple quote character. - quote1 = quote[-1] - if len(docstring) and docstring[-1] == quote1: - docstring = docstring[:-1] + "\\" + quote1 - - # Escape triple quote when needed - if quote == '"""': - replace_str = '\\"""' - else: - assert quote == "'''" - replace_str = "\\'''" - - docstring = docstring.replace(quote, replace_str) - docstring = docstring.replace("\t", "\\\\") - - lines = docstring.split("\n") - - self.write(quote) - if len(lines) == 0: - self.println(quote) - elif len(lines) == 1: - self.println(lines[0], quote) - else: - self.println(lines[0]) - for line in lines[1:-1]: - if line: - self.println(line) - else: - self.println("\n\n") - pass - pass - self.println(lines[-1], quote) + print_docstring(self, indent, docstring) self.prune() def n_elifelsestmtr(self, node: SyntaxTree): From 7db6a272afc936f913c78add7a3d442fceaca4cc Mon Sep 17 00:00:00 2001 From: gdesmar <75089569+gdesmar@users.noreply.github.com> Date: Wed, 16 Oct 2024 20:19:39 +0000 Subject: [PATCH 3/3] Adding tests for bytestring docstring --- test/bytecode_2.7/16_bytestring_docstring.pyc | Bin 0 -> 1733 bytes .../16_no_bytestring_docstring.pyc | Bin 0 -> 1242 bytes .../stmts/16_bytestring_docstring.py | 45 ++++++++++++++++++ .../stmts/16_no_bytestring_docstring.py | 45 ++++++++++++++++++ 4 files changed, 90 insertions(+) create mode 100644 test/bytecode_2.7/16_bytestring_docstring.pyc create mode 100644 test/bytecode_3.8/16_no_bytestring_docstring.pyc create mode 100644 test/simple_source/stmts/16_bytestring_docstring.py create mode 100644 test/simple_source/stmts/16_no_bytestring_docstring.py diff --git a/test/bytecode_2.7/16_bytestring_docstring.pyc b/test/bytecode_2.7/16_bytestring_docstring.pyc new file mode 100644 index 0000000000000000000000000000000000000000..0d4114e12f13b9ca383b64a99b398579f0550427 GIT binary patch literal 1733 zcmb_c&2G~`5T0E-wv!T6Qh_QCC?^yymAG)KC{2YpQ6cw4F00huR)sW1+3lf6eqMni zkHM?(3OoSfikNR4$BtT&6o|Bw-TD3U%}jzH-OlHD^E9LRC*bdAeB7=g%85oS73CY0 zYx+d=k?8e^-vQ;fC=VAZO?eBC5gQ`8gk&YbTTSj2`4)XpWCMD`%9xxm4oP!H}BBVpbHi^S-dRri;3;$MdtkMYXvMi{_; zCB?Ov52c=uIl>tJCC2#MeBXD@&iq+1eLkBNvjGbG5LxZyWWe7f!rkZF<0s}A5QPGy zC~rIOE`5j1*<|dTIk}i-5x*SZlOD8K`hDgMx#nhI${issgQtZ0F-hlVzZPr-f)ZtC2BLosyVK^w$2oL{Kb^a z$bt!KusKKVu4nElv`VuWw!;RHHYY3*@`X~gG)*AHuvkD@pRvf}Ml@npOrUJ}Zn@V_ gvDNM&i%4xHTS+@?hdq5)#q+bR+G<;M_*LG11Kun=jQ{`u literal 0 HcmV?d00001 diff --git a/test/bytecode_3.8/16_no_bytestring_docstring.pyc b/test/bytecode_3.8/16_no_bytestring_docstring.pyc new file mode 100644 index 0000000000000000000000000000000000000000..6d41643df181453101dc32807728965eb31dac0b GIT binary patch literal 1242 zcmb7Dv2NQi5G5&EqHWnw(x4~;6!1_K$P%DSr=W>l6afmp zKB8kYYUwBRD>`W^(7*81JJPWgz#T&1&b$*J-`(T+bEnfHusXZR`7S5qF9!7$KyUvTX5HZzI;T=f>6)6F~Tm#~Y*@L1nqdK@GstM6YAI%9R znnSL2CF~cM<1R;+IpcElGF-+pAJ0h|>1dVx?y}L3@E-4DaJCH`KV6o&QyBm9F<^xj ztL$%=6&|ZvCuA>PB%g9Mo#>v*$F?vR+4&gyezX`wM_{%GPLq^^Doh880?$stXP}M> zp!K&k%qHLpP!;fTK><%rNXdo{RkA9Q5{i+s>h`VGrntzn z560xCq!qV%a#j-4gc}ww-@KJsE>CX@?JGx^-|c_Bty<&B$Xa;{N{n z!>|l1A!RnY*1*@2^4f_3`&i1G>1g7=m!<|BLww zjy;H}Xc{a9eX&W1V7riX+4Y1k6CrHcSNdmJ4WKQ0p!SYOmZrz1z06Xh~t%MrX zg);GDhyyzuz9w!g>LVzp&^qQew!ZoOU6G3|3)5Gh#KU^Y>uOijRof%n8*gI?{*BGE zr_sasnE)VOn@vQ?k_czbu|2P`?I0BChfe3crXLrq#R=icG49lAgep3!=xOZ<)=h~6 gKZNh_KVx5mi_@% literal 0 HcmV?d00001 diff --git a/test/simple_source/stmts/16_bytestring_docstring.py b/test/simple_source/stmts/16_bytestring_docstring.py new file mode 100644 index 00000000..ab700011 --- /dev/null +++ b/test/simple_source/stmts/16_bytestring_docstring.py @@ -0,0 +1,45 @@ +"""Module docstring""" +class A: + b"""Got \xe7\xfe Bytes?""" + assert __doc__ == b"""Got \xe7\xfe Bytes?""" + + def class_func(self): + b"""Got \xe7\xfe Bytes?""" + assert __doc__ == """Module docstring""" + +class B: + """Got no Bytes?""" + assert __doc__ == """Got no Bytes?""" + + def class_func(self): + """Got no Bytes?""" + assert __doc__ == """Module docstring""" + +def single_func(): + """single docstring?""" + assert __doc__ == """Module docstring""" + +def single_byte_func(): + b"""Got \xe7\xfe Bytes?""" + assert __doc__ == """Module docstring""" + +assert __doc__ == """Module docstring""" + +assert single_func.__doc__ == """single docstring?""" +single_func() + +assert single_byte_func.__doc__ == b"""Got \xe7\xfe Bytes?""" +single_byte_func() + +assert A.__doc__ == b"""Got \xe7\xfe Bytes?""" +assert A.class_func.__doc__ == b"""Got \xe7\xfe Bytes?""" +a = A() +assert a.class_func.__doc__ == b"""Got \xe7\xfe Bytes?""" +a.class_func() + +assert B.__doc__ == """Got no Bytes?""" +assert B.class_func.__doc__ == """Got no Bytes?""" +b = B() +assert b.class_func.__doc__ == """Got no Bytes?""" +b.class_func() + diff --git a/test/simple_source/stmts/16_no_bytestring_docstring.py b/test/simple_source/stmts/16_no_bytestring_docstring.py new file mode 100644 index 00000000..be716799 --- /dev/null +++ b/test/simple_source/stmts/16_no_bytestring_docstring.py @@ -0,0 +1,45 @@ +"""Module docstring""" +class A: + b"""Got \xe7\xfe Bytes?""" + assert __doc__ == """Module docstring""" + + def class_func(self): + b"""Got \xe7\xfe Bytes?""" + assert __doc__ == """Module docstring""" + +class B: + """Got no Bytes?""" + assert __doc__ == """Got no Bytes?""" + + def class_func(self): + """Got no Bytes?""" + assert __doc__ == """Module docstring""" + +def single_func(): + """single docstring?""" + assert __doc__ == """Module docstring""" + +def single_byte_func(): + b"""Got \xe7\xfe Bytes?""" + assert __doc__ == """Module docstring""" + +assert __doc__ == """Module docstring""" + +assert single_func.__doc__ == """single docstring?""" +single_func() + +assert single_byte_func.__doc__ is None +single_byte_func() + +assert A.__doc__ is None +assert A.class_func.__doc__ is None +a = A() +assert a.class_func.__doc__ is None +a.class_func() + +assert B.__doc__ == """Got no Bytes?""" +assert B.class_func.__doc__ == """Got no Bytes?""" +b = B() +assert b.class_func.__doc__ == """Got no Bytes?""" +b.class_func() +