berkerpeksag / astor

Python AST read/write
https://pypi.org/project/astor/
BSD 3-Clause "New" or "Revised" License
810 stars 102 forks source link

Fixing the bug preventing usage of custom dumpers #151

Closed KOLANICH closed 4 years ago

KOLANICH commented 5 years ago

@berkerpeksag,

KaitaiPowerWorkaround.py ```python from plumbum import cli from ast import * import astor # https://patch-diff.githubusercontent.com/raw/berkerpeksag/astor/pull/151.patch is absolutely needed, as fixes a bug in astor, https://patch-diff.githubusercontent.com/raw/berkerpeksag/astor/pull/152.patch is needed for using hex to make the expr a bit shorter import typing class KaitaiGen(astor.SourceGenerator): def visit_IfExp(self, node): with self.delimit(node) as delimiters: astor.code_gen.set_precedence(delimiters.p + 1, node.body, node.test) astor.code_gen.set_precedence(delimiters.p, node.orelse) self.write("(", node.test, " ? ", node.body, " : ", node.orelse, ")") def extractPowerOf2(base: int) -> (int, int): c = 0 while base % 2 == 0: base //= 2 c += 1 return base, c SGT = typing.Type[KaitaiGen] def square_and_multiply(base: int, bits: int = 8, argName: str = "log", generator: SGT = None) -> str: """ONLY FOR POSITIVE POWERS!!! Process negative ones yourself.""" if generator is None: generator = KaitaiGen baseR, powOf2 = extractPowerOf2(base) if powOf2 != 0: if powOf2 != 1: sh = BinOp(left=Name(id=argName), op=Mult(), right=Num(n=powOf2)) else: sh = Name(id=argName) res = BinOp(left=Num(n=1), op=LShift(), right=sh) else: res = Num(n=1) if baseR != 1: exp = baseR b2Base = 1 for i in range(bits): res = BinOp( left=res, op=Mult(), right=IfExp( test=Attribute( value=BinOp( left=Name(id=argName), op=BitAnd(), right=Num(n=b2Base) ), attr="as", ), body=Num(n=exp), orelse=Num(n=1), ), ) exp *= exp b2Base = b2Base << 1 return astor.to_source(res, indent_with="", source_generator_class=generator, pretty_source=lambda source: "".join(source)).strip() class PowerWorkaroundCLI(cli.Application): def main(self, base: int, bits: int = 8, argName: str = "log"): print("".join("# "+l for l in square_and_multiply.__doc__.splitlines())) print('value: "'+square_and_multiply(base, bits, argName)+'"') if __name__ == "__main__": PowerWorkaroundCLI.run() ```

Please note that the functionality I am fixing in this PR is already present in astor, it is just broken because of a mistake.

berkerpeksag commented 4 years ago

Thank you very much! This has been fixed in https://github.com/berkerpeksag/astor/commit/51c9e70f1b3a8877cb531ab9c5b1a814eefe7532.