Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Bug] f-string with hasattr causes an import error #1954

Open
BertLindeman opened this issue Nov 28, 2024 · 12 comments
Open

[Bug] f-string with hasattr causes an import error #1954

BertLindeman opened this issue Nov 28, 2024 · 12 comments
Labels
bug Something isn't working software: pybricks-code Issues with https://code.pybricks.com application

Comments

@BertLindeman
Copy link

BertLindeman commented Nov 28, 2024

Describe the bug
Using hasattr in an f-string causes an import error (There is no import error).
The same data in a .format does not produce that error.

To reproduce
Steps to reproduce the behavior:

  1. copy this program:
import mission_run_1
missions = [("1", irrelevant_name, "first"), ("2", "stop", "stop"),]
print(f"hasattr f-string {hasattr(missions[0][1], "run")}")  # import error
# print("hasattr format  {}".format(hasattr(missions[0][1], "run")))  # OK name error
  1. make sure you have a program loaded with the module name of the import
  2. run the problem code and see ImportError: no module named 'mission_run_1'
  3. comment the first print and uncomment the second
  4. Run again and see no ImportError, but the correct NameError

Expected behavior
The same correct behavior for the f-string and the formatted one.
And most of all: No incorrect flagging the import as error.

Took me quiet some time to assure that the import statement was correct 😄

Screenshots
There is a saying that a picture is worth a 1000 words. Screenshots really help to identify and solve problems.
None sofar.

Extra info

  1. Have looked at pybricks issues and micropython issues could not find something similar.
  2. I think the f-strings are re-written during compile, so the problem might be in that phase. Yet strange that the format I show does not have the problem.
  3. Tested on beta and stable versions.
@BertLindeman BertLindeman added the triage Issues that have not been triaged yet label Nov 28, 2024
@dlech
Copy link
Member

dlech commented Nov 29, 2024

I assume this works with pybricksdev instead of Pybricks Code?

Sounds like a bug with the Python parser we use for import detection in Pybricks Code.

@dlech dlech added bug Something isn't working software: pybricks-code Issues with https://code.pybricks.com application and removed triage Issues that have not been triaged yet labels Nov 29, 2024
@BertLindeman
Copy link
Author

BertLindeman commented Nov 29, 2024

I assume this works with pybricksdev instead of Pybricks Code?

Will try tonight.

[EDIT] Why not now.... @dlech

pybricksdev v1.0.0a52
pybricksdev run -n "prime beta" ble issue_1954_fstring_problem.py
Searching for prime beta...
Traceback (most recent call last):
  File "<frozen runpy>", line 198, in _run_module_as_main
  File "<frozen runpy>", line 88, in _run_code
  File "C:\Python311\Scripts\pybricksdev.exe\__main__.py", line 7, in <module>
  File "C:\Python311\Lib\site-packages\pybricksdev\cli\__init__.py", line 446, in main
    asyncio.run(subparsers.choices[args.tool].tool.run(args))
  File "C:\Python311\Lib\asyncio\runners.py", line 190, in run
    return runner.run(main)
           ^^^^^^^^^^^^^^^^
  File "C:\Python311\Lib\asyncio\runners.py", line 118, in run
    return self._loop.run_until_complete(task)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Python311\Lib\asyncio\base_events.py", line 653, in run_until_complete
    return future.result()
           ^^^^^^^^^^^^^^^
  File "C:\Python311\Lib\site-packages\pybricksdev\cli\__init__.py", line 204, in run
    await hub.run(script_path, args.wait)
  File "C:\Python311\Lib\site-packages\pybricksdev\connections\pybricks.py", line 572, in run
    mpy = await compile_multi_file(py_path, abi)
          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Python311\Lib\site-packages\pybricksdev\compile.py", line 121, in compile_multi_file
    finder.run_script(path)
  File "C:\Python311\Lib\modulefinder.py", line 153, in run_script
    self.load_module('__main__', fp, pathname, stuff)
  File "C:\Python311\Lib\modulefinder.py", line 332, in load_module
    co = compile(fp.read(), pathname, 'exec')
         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "issue_1954_fstring_problem.py", line 4
    print(f"hasattr f-string {hasattr(missions[0][1], "run")}")  # import error
                                                       ^^^
SyntaxError: f-string: unmatched '('

@BertLindeman
Copy link
Author

So in the end a user syntax error. But a nasty way of showing it.
Fixed the quotes and so "fixed" the error.

@dlech dlech added the software: pybricks-micropython Issues with Pybricks MicroPython firmware (or EV3 runtime) label Nov 29, 2024
@dlech
Copy link
Member

dlech commented Nov 29, 2024

Thanks for checking. So more a bug in MicroPython for not catching the syntax error.

@dlech dlech removed the software: pybricks-code Issues with https://code.pybricks.com application label Nov 29, 2024
@BertLindeman
Copy link
Author

Thanks for checking. So more a bug in MicroPython for not catching the syntax error.

Running MicroPython v1.22.1+ds-1build2 on 2024-04-01; linux [GCC 13.2.0] version
this program (removed the comments)

import mission_run_1
missions = [("1", irrelevant_name, "first"), ("2", "stop", "stop"),]
print(f"hasattr f-string {hasattr(missions[0][1], "run")}")

Shows:

Traceback (most recent call last):
  File "issue_1954_fstring_problem_syntax.py", line 2, in <module>
  File "/home/bert/py/pybricks/issue/mission_run_1.py", line 3, in <module>
ImportError: no module named 'pybricks'

I do not know the phases but I would expect the syntax being found before the import being done.

Will look if I can get the "source" more simple to show that the syntax error is not catched.

Bert

@dlech
Copy link
Member

dlech commented Nov 29, 2024

I see. The code works fine in MicroPython if there are no imports since MicroPython seems to allow " withing f-string with f" while standard Python does not.

pybricksdev reports a syntax error because it uses the CPython compiler to find imports.

Pybricks Code uses static analysis tool find imports and silently fails on syntax errors assuming that any syntax error it detects would also be a syntax error in MicroPython. But since this is not a syntax error in MicroPython, the program compiles and runs but the proper imports were not included because the import analyzer detected the syntax error.

@dlech dlech added the software: pybricks-code Issues with https://code.pybricks.com application label Nov 29, 2024
@dlech
Copy link
Member

dlech commented Nov 29, 2024

minimal test case:

import a
print(f"{"x"}")

@BertLindeman
Copy link
Author

Simplified to:

print(f"{"run"}")
print("{"run"}")

The first line should report a syntax error, but in these versions the second line does.

Tested on micropython v1.22.1+ds-1build2 on 2024-04-01
and the same error I see on python3.12.3
I see no issue on Cpython.
Will try to make one there.

@BertLindeman
Copy link
Author

Added cpython issue 127428 Unexpected behavior in f-strings with nested quotes

@BertLindeman
Copy link
Author

BertLindeman commented Nov 30, 2024

JelleZijlstra pointed to PEP 701 – Syntactic formalization of f-strings
So in python 3.12 this is correct syntax.

[EDIT]
With this in mind I re-tested the f-string on MicroPython v1.22.1+ds-1build2 on 2024-04-01; linux [GCC 13.2.0] version

>>> print(f"{"run"}")
run

So leave this until pybricks uses micropython 1.22?
The circumvention to use a string.format is there.

@dlech dlech removed the software: pybricks-micropython Issues with Pybricks MicroPython firmware (or EV3 runtime) label Nov 30, 2024
@dlech
Copy link
Member

dlech commented Nov 30, 2024

I don't see how updating the MicroPython version will make a difference. The problem is that the Python parser for finding imports in Pybricks Code hasn't been updated to support the Python 3.12 syntax. MicroPython isn't involved in this part of the code at all.

@BertLindeman
Copy link
Author

I stand corrected 😄

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working software: pybricks-code Issues with https://code.pybricks.com application
Projects
None yet
Development

No branches or pull requests

2 participants