<html><head><meta http-equiv="content-type" content="text/html; charset=utf-8"></head><body dir="auto">Have you looked at the built-in AST module, ast? <a href="https://docs.python.org/3/library/ast.html">https://docs.python.org/3/library/ast.html</a><div><br></div><div>I don’t see anything preventing you from walking the AST Python itself can give you- you’d look for two Set AST nodes if we were to do {{ }}.</div><div><br></div><div>There’s also the parser built-in module. You can use it if you first use dis.code_info to get the source then re-parse it. It helps with parse trees. Parse trees are generated before the AST I think. You’d use the parser module’s ST objects with the token module’s constants, for example token.LBRACE or token.RBRACE.<div><br><div>Have you looked at the built-in dis module? You can use dis.code_info(obj) to get the string of the function. Then you could look for your specified syntax with regex and recompile that with the ast module.</div><div><br><div id="AppleMailSignature" dir="ltr">Sent from my iPhone</div><div dir="ltr"><br>On Sep 25, 2018, at 1:49 AM, Marko Ristin-Kaufmann <<a href="mailto:marko.ristin@gmail.com">marko.ristin@gmail.com</a>> wrote:<br><br></div><blockquote type="cite"><div dir="ltr"><div dir="ltr"><div dir="ltr"><div dir="ltr"><div><div>Hi James,<br></div>Thanks for the feedback!<br><br>I also thought about decompiling the condition to find its AST and figure out what old values are needed. However, this is not so easily done at the moment as all the decompilation libraries I looked at (meta, ucompyle6) are simply struggling to keep up with the development of the python bytecode. In other words, the decompiler needs to be updated with every new version of python which is kind of a loosing race (unless the python devs themselves don't provide this functionality which is not the case as far as I know).<br><br></div>There is macropy (<a href="https://github.com/lihaoyi/macropy">https://github.com/lihaoyi/macropy</a>) which was suggested on the other thread (<a href="https://groups.google.com/forum/#!topic/python-ideas/dmXz_7LH4GI">https://groups.google.com/forum/#!topic/python-ideas/dmXz_7LH4GI</a>) that I'm currently looking at.<br><br></div><div>Cheers,<br></div><div>Marko<br></div><div dir="ltr"><br></div></div><br><div class="gmail_quote"><div dir="ltr">On Tue, 25 Sep 2018 at 00:35, James Lu <<a href="mailto:jamtlu@gmail.com">jamtlu@gmail.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">You could disassemble (import dis) the lambda to biew the names of the lambdas.<br>
<br>
@before(lambda self, key, _, length, get: self.length(), self.get(key))<br>
<br>
Perhaps you could disassemble the function code and look at all operations or accesses that are done to “old.” and evaluate those expressions before the function runs. Then you could “replace” the expression.<br>
@post(lambda self, key, old: old.get is None and old.length + 1 ==<br>
self.length())<br>
<br>
Either the system would grab old.get and old.length or be greedy and grab old.get is None and old.length + 1. It would then replace the old.get and old.length with injects that only respond to is None and +1.<br>
<br>
Or, a syntax like this <br>
@post(lambda self, key, old: [old.get(old.key)] is None and [old.self.length() + 1] ==<br>
self.length())<br>
<br>
Where the stuff inside the brackets is evaluated before the decorated function runs. It would be useful for networking functions or functions that do something ephemeral, where data related to the value being accessed needed for the expression no longer exists after the function. <br>
<br>
This does conflict with list syntax forever, so maybe either force people to do list((expr,)) or use an alternate syntax like one item set syntax { } or double set syntax {{ }} or double list syntax [[ ]]. Ditto with having to avoid the literals for the normal meaning.<br>
<br>
You could modify Python to accept any expression for the lambda function and propose that as a PEP. (Right now it’s hardcoded as a dotted name and optionally a single argument list surrounded by parentheses.)<br>
<br>
I suggest that instead of “@before” it’s “@snapshot” and instead of “old” it’s “snapshot”.<br>
<br>
Python does have unary plus/minus syntax as well as stream operators (<<, >>) and list slicing syntax and the @ operator and operators & and | if you want to play with syntax. There’s also the line continuation character for crazy lambdas.<br>
<br>
Personally I prefer<br>
@post(lambda self, key, old: {{old.self.get(old.key)}} and {{old.self.length() + 1}} ==<br>
self.length())<br>
<br>
because it’s explicit about what it does (evaluate the expressions within {{ }} before the function runs. I also find it elegant.<br>
<br>
Alternatively, inside the {{ }} could be a special scope where locals() is all the arguments @pre could’ve received as a dictionary. For either option you can remove the old parameter from the lambda. Example:<br>
@post(lambda self, key: {{self.get(key)}} and {{self.length() + 1}} ==<br>
self.length())<br>
<br>
Perhaps the convention should be to write {{ expr }} (with the spaces in between).<br>
<br>
You’d probably have to use the ast module to inspect it instead of the dis modul. Then find some way to reconstruct the expressions inside the double brackets- perhaps by reconstructing the AST and compiling it to a code object, or perhaps by finding the part of the string the expression is located. dis can give you the code as a string and you can run a carefully crafted regex on it.<br>
_______________________________________________<br>
Python-ideas mailing list<br>
<a href="mailto:Python-ideas@python.org" target="_blank">Python-ideas@python.org</a><br>
<a href="https://mail.python.org/mailman/listinfo/python-ideas" rel="noreferrer" target="_blank">https://mail.python.org/mailman/listinfo/python-ideas</a><br>
Code of Conduct: <a href="http://python.org/psf/codeofconduct/" rel="noreferrer" target="_blank">http://python.org/psf/codeofconduct/</a><br>
</blockquote></div></div>
</div></blockquote></div></div></div></body></html>