Repository navigation
mypyc-related stubtest crash #15923
Copy link
Copy link
Closed
Labels
Description
Bug Report
In typeshed CI stubtest crashes when run against fpdf2 2.7.5 and the current typeshed stubs. It works fine with fpdf2 2.7.4. Please see python/typeshed#10533, or to be more specific the traceback at https://github.com/python/typeshed/actions/runs/5930009431/job/16078844153?pr=10533:
Traceback (most recent call last):
File "/opt/hostedtoolcache/Python/3.10.12/x64/lib/python3.10/runpy.py", line 196, in _run_module_as_main
return _run_code(code, main_globals, None,
File "/opt/hostedtoolcache/Python/3.10.12/x64/lib/python3.10/runpy.py", line 86, in _run_code
exec(code, run_globals)
File "/tmp/tmpo2a_8672/lib/python3.10/site-packages/mypy/stubtest.py", line 1891, in <module>
sys.exit(main())
File "/tmp/tmpo2a_8672/lib/python3.10/site-packages/mypy/stubtest.py", line 1887, in main
return test_stubs(parse_options(sys.argv[1:]))
File "/tmp/tmpo2a_8672/lib/python3.10/site-packages/mypy/stubtest.py", line 1760, in test_stubs
for error in test_module(module):
File "/tmp/tmpo2a_8672/lib/python3.10/site-packages/mypy/stubtest.py", line 223, in test_module
yield from verify(stub, runtime, [module_name])
File "/tmp/tmpo2a_8672/lib/python3.10/site-packages/mypy/stubtest.py", line 401, in verify_mypyfile
yield from verify(stub_entry, runtime_entry, object_path + [entry])
File "/tmp/tmpo2a_8672/lib/python3.10/site-packages/mypy/stubtest.py", line 543, in verify_typeinfo
yield from verify(stub_to_verify, runtime_attr, object_path + [entry])
File "/tmp/tmpo2a_8672/lib/python3.10/site-packages/mypy/stubtest.py", line [100](https://github.com/python/typeshed/actions/runs/5930009431/job/16078844153?pr=10533#step:5:101)6, in verify_funcitem
for message in _verify_signature(stub_sig, runtime_sig, function_name=stub.name):
File "/tmp/tmpo2a_8672/lib/python3.10/site-packages/mypy/stubtest.py", line 858, in _verify_signature
yield from _verify_arg_default_value(stub_arg, runtime_arg)
File "/tmp/tmpo2a_8672/lib/python3.10/site-packages/mypy/stubtest.py", line 632, in _verify_arg_default_value
runtime_type = get_mypy_type_of_runtime_value(runtime_arg.default)
File "/tmp/tmpo2a_8672/lib/python3.10/site-packages/mypy/stubtest.py", line 1563, in get_mypy_type_of_runtime_value
return mypy.types.LiteralType(value=value, fallback=fallback)
File "mypy/types.py", line 2584, in __init__
TypeError: union[int, str, bool, float] object expected; got None
This error seems to be generated by mypyc. I can't reproduce it locally, possibly because mypyc is not used?
Your Environment
- Mypy version used: 1.5.1
- Mypy command-line flags:
/tmp/tmpo2a_8672/bin/pip install fpdf2[]==2.7.5 mypy==1.5.1
MYPYPATH=/home/runner/work/typeshed/typeshed/stubs/fpdf2:/home/runner/work/typeshed/typeshed/stubs/Pillow /tmp/tmpo2a_8672/bin/python -m mypy.stubtest --custom-typeshed-dir /home/runner/work/typeshed/typeshed fpdf --allowlist /home/runner/work/typeshed/typeshed/stubs/fpdf2/@tests/stubtest_allowlist.txt
- Python version used: 3.10.12
Reactions are currently unavailable
Activity
AlexWaygood commentedon Aug 22, 2023
I can reproduce this crash locally on Python 3.9 and Python 3.10, but not Python 3.11
AlexWaygood commentedon Aug 22, 2023
And, as @srittau says, the crash only occurs with a compiled version of mypy, which makes it tricky to debug!
AlexWaygood commentedon Aug 22, 2023
Looks like the TypeError is raised when mypy is trying to validate the default value typeshed gives for one of the parameters in this
__init__method: https://github.com/py-pdf/fpdf2/blob/ff55d983a0b6d601a78628a45747234fbca59e26/fpdf/encryption.py#L127-L135AlexWaygood commentedon Aug 22, 2023
I confirmed locally that applying this diff to typeshed's stubs makes the crash go away:
AlexWaygood commentedon Aug 22, 2023
The issue is this call here:
mypy/mypy/stubtest.py
Line 1563 in 7141d6b
When attempting to validate the
permissionparameter onfpdf.encryption.StandardSecurityHandler.__init__, stubtest ends up trying to callmypy.types.LiteralType(value=None, fallback=fpdf.enums.AccessPermission). That goes against the type annotation formypy.types.LiteralType.__init__, which says thatvalueshould only ever beint,str,boolorfloat:mypy/mypy/types.py
Lines 2560 to 2578 in 7141d6b
Inserting a
reveal_type()call indicates that mypy believes thatvaluecan only be anintor astrhere, which is why the type violation is only being caught by the runtime checks that mypyc inserts when compiling mypy:AlexWaygood commentedon Aug 22, 2023
Here is the reason why stubtest crashes on Python <=3.10 but not on Python 3.11. On Python 3.10:
On Python 3.11:
Python 3.11.4 | packaged by Anaconda, Inc. | (main, Jul 5 2023, 13:47:18) [MSC v.1916 64 bit (AMD64)] on win32 Type "help", "copyright", "credits" or "license" for more information. >>> import fpdf.encryption >>> fpdf.encryption.AccessPermission.all().name 'PRINT_LOW_RES|MODIFY|COPY|ANNOTATION|FILL_FORMS|COPY_FOR_ACCESSIBILITY|ASSEMBLE|PRINT_HIGH_RES'isinstance(fpdf.encryption.AccessPermission.all(), enum.Enum)evaluates toTrue, which means thatvalueis set tofpdf.encryption.AccessPermission.all().namehere:mypy/mypy/stubtest.py
Lines 1556 to 1557 in 7141d6b
But on Python <=3.10,
fpdf.encryption.AccessPermission.all().nameisNone, which triggers the crash.The
fpdf.encryption.AccessPermissionsIntFlagis defined here: https://github.com/py-pdf/fpdf2/blob/34ff166de50a757c8cb32d6f047f0901e052d814/fpdf/enums.py#L801-L834AlexWaygood commentedon Aug 22, 2023
The reason why mypy doesn't pick up that
runtime.namecould beNonehere during the self-check is becauseenum.Flagviolates the Liskov Substitution Principle. Thenameproperty can only ever be astron an instance of anenum.Enumenumeration... unless that enumeration is a subclass ofIntFlag, in which case it could also beNone: https://github.com/python/typeshed/blob/32b750b6aa2396cdaa757da16da8cd8fb627c09f/stdlib/enum.pyi#L216-L217AlexWaygood commentedon Aug 22, 2023
I proposed a fix in #15933. The fix is a one-line change, though finding a way to reproduce the crash in the context of stubtest's test suite was a slight challenge 😄
Fix stubtest mypy enum.Flag edge case (#15933)