unrpyc
unrpyc copied to clipboard
AttributeError: 'RawBlock' object has no attribute 'statements'
Ran into an error when decompiling a free game. The full stacktrace:
Traceback (most recent call last):
File "/data/bulky/games/x/util/unrpyc/unrpyc.py", line 260, in worker
return decompile_rpyc(filename, args.clobber, args.dump, no_pyexpr=args.no_pyexpr,
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/data/bulky/games/x/util/unrpyc/unrpyc.py", line 202, in decompile_rpyc
decompiler.pprint(out_file, ast, options)
File "/data/bulky/games/x/util/unrpyc/decompiler/__init__.py", line 54, in pprint
Decompiler(out_file, options).dump(ast)
File "/data/bulky/games/x/util/unrpyc/decompiler/__init__.py", line 109, in dump
super(Decompiler, self).dump(ast, skip_indent_until_write=True)
File "/data/bulky/games/x/util/unrpyc/decompiler/util.py", line 49, in dump
self.print_nodes(ast)
File "/data/bulky/games/x/util/unrpyc/decompiler/util.py", line 140, in print_nodes
self.print_node(node)
File "/data/bulky/games/x/util/unrpyc/decompiler/__init__.py", line 122, in print_node
self.dispatch.get(type(ast), type(self).print_unknown)(self, ast)
File "/data/bulky/games/x/util/unrpyc/decompiler/__init__.py", line 499, in print_init
self.print_nodes(ast.block)
File "/data/bulky/games/x/util/unrpyc/decompiler/util.py", line 140, in print_nodes
self.print_node(node)
File "/data/bulky/games/x/util/unrpyc/decompiler/__init__.py", line 122, in print_node
self.dispatch.get(type(ast), type(self).print_unknown)(self, ast)
File "/data/bulky/games/x/util/unrpyc/decompiler/__init__.py", line 170, in print_image
self.print_atl(ast.atl)
File "/data/bulky/games/x/util/unrpyc/decompiler/__init__.py", line 127, in print_atl
self.linenumber = atldecompiler.pprint(
^^^^^^^^^^^^^^^^^^^^^
File "/data/bulky/games/x/util/unrpyc/decompiler/atldecompiler.py", line 7, in pprint
return ATLDecompiler(out_file, options).dump(
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/data/bulky/games/x/util/unrpyc/decompiler/atldecompiler.py", line 26, in dump
self.print_block(ast)
File "/data/bulky/games/x/util/unrpyc/decompiler/atldecompiler.py", line 45, in print_block
if block.statements:
^^^^^^^^^^^^^^^^
AttributeError: 'RawBlock' object has no attribute 'statements'
If you'd like to reproduce it, grab https://hatchet-games.itch.io/maeves-academy and try decompiling the file goth_wardrobe.rpyc.
I'm using v2.0.0. Worked fine on all the other files, so it's probably not my environment.
(Thanks for the Py3 update!)
~Ok, this was a breeze. I got this already and can make later a pull req for it.~
Basically "RawBlock" can be without attrs(fix this and more will come) and we need now to check against it. Like in many other places in the last years. I have the feeling that's not last we've seen of this type of bug.
Edit: A little bit too fast... With the fix (dev_fix_ish197) it decompiles without error but the resulting .rpy is "strange". A lot of image statement blocks without content. goth_wardrobe.zip
Basically "RawBlock" can be without attrs(fix this and more will come) and we need now to check against it. Like in many other places in the last years.
Huh, I wonder what causes that. renpy should unconditionally assign self.statements in RawBlock.__init__.
I have a feeling more is afoot there.
Try decompiling that single file with legacy ;)
Damn. I had the thought to try this, so why didn't i? 😩 So my other thought could very well also fit: A legacy game put on v8 without forced recompile, huh?
@zorbathut
- Could you look in which Ren'Py version the previous game versions run? I'm curious.
- To decompile this app you need to run the unrpyc legacy (v1.3 with python2).
To decompile this app you need to run the unrpyc legacy (v1.3 with python2).
No, only to decompile that single file. The rest was compiled with 8.1, go figure why.
@zorbathut
* Could you look in which Ren'Py version the previous game versions run? I'm curious.
I'm afraid I don't actually have any older versions, nor do I see a way to get them off Itch.
* To decompile this app you need to run the unrpyc legacy (v1.3 with python2).
Aha, wild. Not going to worry about this for now then! Thanks for looking into it :)
No, only to decompile that single file.
Strange. I decompiled and astdumped everything error free with v1.3.0. Tested the game even a few minutes(fast skip) and encountered no issues. Very curious.
The rest was compiled with 8.1, go figure why.
Ah no. I found a few more in there from different dates all the way back to 2022, but the most are as you said. 🤷🏻 More riddles...
Strange. I decompiled and astdumped everything error free with v1.3.0. Tested the game even a few minutes(fast skip) and encountered no issues. Very curious.
Seems for everything I ripped out of either, both legacy and master are still pretty decent at decompiling stuff from either py2 or py3 based renpy. Honestly pretty surprising.
Just FYI, I'm fine with this being either closed or kept open for discussion. If possible, though, I'd request some check to ensure you're using the right version - I'm certain I won't be the last person to report something that ends up being "wrong renpy version", and a more descriptive error message would go a long way to stop that.
This assumes there's a good way for code to tell which version the .rpyc is, though.
. . . although, given the discussion here, maybe with an optional flag to try anyway. Or do the check only on error.
I'm currently of the opinion that doing both is a good idea. I've added some detection, but the format makes it hard to detect all. That said, if we can't detect it, we might just be able to decompile it decently. The detection just prints a warning, and I'll add back a few pre ren'py 8 features (basically just ubiquitous parameter / argument handling). That will likely be enough to support basically every ren'py 7 game as well. Not sure how much more it'd be able to decently handle. 6.17 is the first I know it definitely won't as that requires old-style screenlang handling. Rest is some much more minor backwards compatibility hazards.
See #199
This has all been implemented.