Support for match-case statement: AttributeError: 'Unparser' object has no attribute '_Match'
bjoernma opened this issue · comments
As pyflowchart 0.3.1 used with python 3.11 and astunparse 1.6.3 throws an exception:
Traceback (most recent call last): File "/usr/lib/python3.10/runpy.py", line 196, in _run_module_as_main return _run_code(code, main_globals, None, File "/usr/lib/python3.10/runpy.py", line 86, in _run_code exec(code, run_globals) File "/home/bjorn/.local/lib/python3.10/site-packages/pyflowchart/__main__.py", line 115, in <module> main(args.code_file, args.field, args.inner, args.output, args.no_simplify, args.conds_align) File "/home/bjorn/.local/lib/python3.10/site-packages/pyflowchart/__main__.py", line 85, in main flowchart = Flowchart.from_code(code, File "/home/bjorn/.local/lib/python3.10/site-packages/pyflowchart/flowchart.py", line 102, in from_code p = parse(f, simplify=simplify, conds_align=conds_align) File "/home/bjorn/.local/lib/python3.10/site-packages/pyflowchart/ast_node.py", line 659, in parse node = ast_node_class(ast_object, **kwargs) File "/home/bjorn/.local/lib/python3.10/site-packages/pyflowchart/ast_node.py", line 137, in __init__ self.body_head, self.body_tails = self.parse_func_body(**kwargs) File "/home/bjorn/.local/lib/python3.10/site-packages/pyflowchart/ast_node.py", line 158, in parse_func_body p = parse(self.ast_object.body, **kwargs) File "/home/bjorn/.local/lib/python3.10/site-packages/pyflowchart/ast_node.py", line 659, in parse node = ast_node_class(ast_object, **kwargs) File "/home/bjorn/.local/lib/python3.10/site-packages/pyflowchart/ast_node.py", line 463, in __init__ OperationNode.__init__(self, operation=self.ast_to_source()) File "/home/bjorn/.local/lib/python3.10/site-packages/pyflowchart/ast_node.py", line 33, in ast_to_source return astunparse.unparse(self.ast_object).strip() File "/home/bjorn/.local/lib/python3.10/site-packages/astunparse/__init__.py", line 13, in unparse Unparser(tree, file=v) File "/home/bjorn/.local/lib/python3.10/site-packages/astunparse/unparser.py", line 38, in __init__ self.dispatch(tree) File "/home/bjorn/.local/lib/python3.10/site-packages/astunparse/unparser.py", line 65, in dispatch meth = getattr(self, "_"+tree.__class__.__name__) AttributeError: 'Unparser' object has no attribute '_Match'
I looked into a solution. It now seems that replacing astunparse with the inbuild package ast package (see e.g. simonpercivall/astunparse#56 (comment)) doesnt throw this and works atm.
Thanks for reporting. I'm on it!
@bjoernma would you mind to provide some more detailed information about how you triggered the exception. I think I've fixed it (by following the solution you mentioned), but I haven't been able to reproduce the problem to test it. So I am not sure if there are any further bugs that prevent you from using PyFlowchart freely.
Able to replicate using python 3.10.11
, pyflowchart 0.3.1
, and astunparse 1.6.3
on a new Repl on Replit. Happened after adding a match-case block to my code. Traceback generated follows:
Traceback (most recent call last):
File "/nix/store/xf54733x4chbawkh1qvy9i1i4mlscy1c-python3-3.10.11/lib/python3.10/runpy.py", line 196, in _run_module_as_main
return _run_code(code, main_globals, None,
File "/nix/store/xf54733x4chbawkh1qvy9i1i4mlscy1c-python3-3.10.11/lib/python3.10/runpy.py", line 86, in _run_code
exec(code, run_globals)
File "/home/runner/Hollow-Knight-Charm-Build-Randomiser/.pythonlibs/lib/python3.10/site-packages/pyflowchart/__main__.py", line 115, in <module>
main(args.code_file, args.field, args.inner, args.output, args.no_simplify, args.conds_align)
File "/home/runner/Hollow-Knight-Charm-Build-Randomiser/.pythonlibs/lib/python3.10/site-packages/pyflowchart/__main__.py", line 85, in main
flowchart = Flowchart.from_code(code,
File "/home/runner/Hollow-Knight-Charm-Build-Randomiser/.pythonlibs/lib/python3.10/site-packages/pyflowchart/flowchart.py", line 102, in from_code
p = parse(f, simplify=simplify, conds_align=conds_align)
File "/home/runner/Hollow-Knight-Charm-Build-Randomiser/.pythonlibs/lib/python3.10/site-packages/pyflowchart/ast_node.py", line 659, in parse
node = ast_node_class(ast_object, **kwargs)
File "/home/runner/Hollow-Knight-Charm-Build-Randomiser/.pythonlibs/lib/python3.10/site-packages/pyflowchart/ast_node.py", line 463, in __init__
OperationNode.__init__(self, operation=self.ast_to_source())
File "/home/runner/Hollow-Knight-Charm-Build-Randomiser/.pythonlibs/lib/python3.10/site-packages/pyflowchart/ast_node.py", line 33, in ast_to_source
return astunparse.unparse(self.ast_object).strip()
File "/home/runner/Hollow-Knight-Charm-Build-Randomiser/.pythonlibs/lib/python3.10/site-packages/astunparse/__init__.py", line 13, in unparse
Unparser(tree, file=v)
File "/home/runner/Hollow-Knight-Charm-Build-Randomiser/.pythonlibs/lib/python3.10/site-packages/astunparse/unparser.py", line 38, in __init__
self.dispatch(tree)
File "/home/runner/Hollow-Knight-Charm-Build-Randomiser/.pythonlibs/lib/python3.10/site-packages/astunparse/unparser.py", line 65, in dispatch
meth = getattr(self, "_"+tree.__class__.__name__)
AttributeError: 'Unparser' object has no attribute '_Match'
Thanks, @AzureArmageddon. There seem to be more jobs to do aside the compatibility of astunparse package to support the new match
statement. I am considering literal convert the match-case
back into the if-else
statement OR a new kind of AstNode would be required to support it.
Since a multi-branch condition node is not supported by flowchart.js
(See #13 for details), even though we have introduced a conds-align feature which may be useful, supporting for match could be really hard. 😭
As the match-case
statement has been widely adopted today, I recommend that those encountering this problem consider a quick fix:
- Make a copy of the code you want to create a flowchart for.
- Rewrite your
match-case
code into anif-elif-else
block. - Try running pyflowchart on the modified version.
- The conds-align feature can help improve the readability of the generated flowchart.
Progress:
With my latest commit 12fcc03, PyFlowchart is now able to read & parse the match sentences (with Python 3.10+).
As mentioned before,
Since a multi-branch condition node is not supported by
flowchart.js
(See #13 for details), even though we have introduced a conds-align feature which may be useful, supporting for match could be really hard. 😭
I have no choice but to make each case in the match a condition node (looks like a if
without else
) and connect them one by one.
For example:
def test_match(a, b, c):
if a > 0:
match b:
case 1:
print('ab')
case 2:
print('abc')
c = 1 + b + a
case 3:
print('nested match')
match c:
case["a"]:
print('a')
case["a", *other_items]:
print('a and others')
case[*first_items, "d"] | (*first_items, "d"):
print('d is the last item')
case _:
print('abcd')
end_of_match()
else:
alez()
end_of_ifs()
Excuse me, this code as a example is a bit verbose (but it covers common use cases, I assume). So the generated flowchart is "a bit" long:
It's definitely not ideal. I have tried to make it more readable (by reusing the conds-align and connection direction features), but it backfired on me:
No one like this bad-routed maze. So I decide to remove all this programic "beautify" features. Just leave it "a bit long".
So, in short, it would appear that astunparse
's inability to parse match-case has been overcome, but flowchart.js
is unable to handle multi-branching conditionals in the exact way we want so this temporary implementation must be used. Not ideal, but that means there is officially a new feature working! 🎉
Perhaps making an issue on flowchart.js
would be appropriate. I don't suppose we can close this issue until flowchart.js
makes changes (or mayhaps if an attractive alternative comes along as a viable replacement)?
Perhaps making an issue on flowchart.js would be appropriate.
There's an existing one that has persisted for years: adrai/flowchart.js#60.
or mayhaps if an attractive alternative comes along as a viable replacement
This is exactly what I am trying to.
I am considering mermaid.js as a potential alternative. Lately, I've favored mermaid.js
over flowchart.js
. However, it's not a straightforward shift due to PyFlowchart's initial design being closely tied to flowchart.js
.
Adopting mermaid.js
will undoubtedly cause significant disruptions to our stable compatibility, which I take pride in since its initial release in 2020 for Python 3.6/3.7.
So I'm still seeking a way to make a refactor that not destroy the current flowchart.js
features, but allow us to add a support for mermaid.js
. (Maybe the silver bullet here is the visitor pattern?)
Anyway, I'm releasing a preview (not well tested) version v0.4.0-alpha.4
that contains current progress for match-case support. pip install pyflowchart==0.4.0a4
to use it.
Keep this issue open for seeking further enhancements.
As pyflowchart 0.3.1 used with python 3.11 and astunparse 1.6.3 throws an exception:
Traceback (most recent call last):
File "C:\Downloads\sc-navigator-model-generation-cp\APO Input Workflow\src\flowchart.py", line 12, in
fc = pfc.parse(code)
^^^^^^^^^^^^^^^
File "C:\Downloads\sc-navigator-model-generation-cp\APO Input Workflow\src\new_env\Lib\site-packages\pyflowchart\ast_node.py", line 659, in parse
node = ast_node_class(ast_object, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "C:\Downloads\sc-navigator-model-generation-cp\APO Input Workflow\src\new_env\Lib\site-packages\pyflowchart\ast_node.py", line 463, in init
OperationNode.init(self, operation=self.ast_to_source())
^^^^^^^^^^^^^^^^^^^^
File "C:\Downloads\sc-navigator-model-generation-cp\APO Input Workflow\src\new_env\Lib\site-packages\pyflowchart\ast_node.py", line 33, in ast_to_source
return astunparse.unparse(self.ast_object).strip()
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "C:\Downloads\sc-navigator-model-generation-cp\APO Input Workflow\src\new_env\Lib\site-packages\astunparse_init_.py", line 13, in unparse
Unparser(tree, file=v)
File "C:\Downloads\sc-navigator-model-generation-cp\APO Input Workflow\src\new_env\Lib\site-packages\astunparse\unparser.py", line 38, in init
self.dispatch(tree)
File "C:\Downloads\sc-navigator-model-generation-cp\APO Input Workflow\src\new_env\Lib\site-packages\astunparse\unparser.py", line 65, in dispatch
meth = getattr(self, "_"+tree.class.name)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
AttributeError: 'Unparser' object has no attribute '_str'. Did you mean: '_Str'?
How do I resolve this issue?
@kaasima10, it appears that your comment may not be related to this thread. Your issue will be traced in #32.