Have you looked at the built-in AST module, ast? https://docs.python.org/3/library/ast.html
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 {{ }}. 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. 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. Sent from my iPhone > On Sep 25, 2018, at 1:49 AM, Marko Ristin-Kaufmann <marko.ris...@gmail.com> > wrote: > > Hi James, > Thanks for the feedback! > > 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). > > There is macropy (https://github.com/lihaoyi/macropy) which was suggested on > the other thread > (https://groups.google.com/forum/#!topic/python-ideas/dmXz_7LH4GI) that I'm > currently looking at. > > Cheers, > Marko > > >> On Tue, 25 Sep 2018 at 00:35, James Lu <jam...@gmail.com> wrote: >> You could disassemble (import dis) the lambda to biew the names of the >> lambdas. >> >> @before(lambda self, key, _, length, get: self.length(), self.get(key)) >> >> 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. >> @post(lambda self, key, old: old.get is None and old.length + 1 == >> self.length()) >> >> 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. >> >> Or, a syntax like this >> @post(lambda self, key, old: [old.get(old.key)] is None and >> [old.self.length() + 1] == >> self.length()) >> >> 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. >> >> 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. >> >> 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.) >> >> I suggest that instead of “@before” it’s “@snapshot” and instead of “old” >> it’s “snapshot”. >> >> 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. >> >> Personally I prefer >> @post(lambda self, key, old: {{old.self.get(old.key)}} and >> {{old.self.length() + 1}} == >> self.length()) >> >> because it’s explicit about what it does (evaluate the expressions within {{ >> }} before the function runs. I also find it elegant. >> >> 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: >> @post(lambda self, key: {{self.get(key)}} and {{self.length() + 1}} == >> self.length()) >> >> Perhaps the convention should be to write {{ expr }} (with the spaces in >> between). >> >> 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. >> _______________________________________________ >> Python-ideas mailing list >> Python-ideas@python.org >> https://mail.python.org/mailman/listinfo/python-ideas >> Code of Conduct: http://python.org/psf/codeofconduct/
_______________________________________________ Python-ideas mailing list Python-ideas@python.org https://mail.python.org/mailman/listinfo/python-ideas Code of Conduct: http://python.org/psf/codeofconduct/