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

"TypeError: unsupported format string passed to NoneType.__format__" while running type inference in version 2.12.x #1856

Closed
crosser opened this issue Oct 28, 2022 · 5 comments · Fixed by #1866
Assignees

Comments

@crosser
Copy link

crosser commented Oct 28, 2022

Steps to reproduce

I have no concise reproducer. Exception happens every time I run pylint on some internal code, with astroid 2.12.10 and 2.12.12 (debian bookworm). It does not happen with earlier versions of astroid (not with version 2.9). The pylinted code itself is "valid", it runs in production here.

Current behavior

When running pylint on some code, I get this exception:

Traceback (most recent call last):
  File "/usr/lib/python3/dist-packages/pylint/utils/ast_walker.py", line 90, in walk
    callback(astroid)
  File "/usr/lib/python3/dist-packages/pylint/checkers/classes/special_methods_checker.py", line 183, in visit_functiondef
    inferred = _safe_infer_call_result(node, node)
  File "/usr/lib/python3/dist-packages/pylint/checkers/classes/special_methods_checker.py", line 42, in _safe_infer_call_result
    value = next(inferit)
  File "/usr/lib/python3/dist-packages/astroid/nodes/scoped_nodes/scoped_nodes.py", line 1749, in infer_call_result
    yield from returnnode.value.infer(context)
  File "/usr/lib/python3/dist-packages/astroid/nodes/node_ng.py", line 159, in infer
    results = list(self._explicit_inference(self, context, **kwargs))
  File "/usr/lib/python3/dist-packages/astroid/inference_tip.py", line 45, in _inference_tip_cached
    result = _cache[func, node] = list(func(*args, **kwargs))
  File "/usr/lib/python3/dist-packages/astroid/brain/brain_builtin_inference.py", line 956, in _infer_str_format_call
    formatted_string = format_template.format(*pos_values, **keyword_values)
TypeError: unsupported format string passed to NoneType.__format__

Expected behavior

TypeError exception should not happen

python -c "from astroid import __pkginfo__; print(__pkginfo__.version)" output

2.12.10,
2.12.12

@jacobtylerwalls
Copy link
Member

Hi @crosser, thanks for the report.

I have no concise reproducer.

We might be able to help you distill one.

pylint produces a crash report, and shows the link in your terminal, like this:

************* Module a
a.py:1:0: F0002: a.py: Fatal error while checking 'a.py'. Please open an issue in our bug tracker so we address this. There is a pre-filled template that you can use in '/Users/.../Library/Caches/pylint/pylint-crash-2022-10-29-08-48-25.txt'. (astroid-error)

The offending file is at the top of the crash report. If the code is too long, or contains sensitive information, you can use the knowledge that the crash happened in _infer_str_format_call to look for calls to .format() on strings. You should be able to then just provide us those calls--and enough surrounding code to rebuild the objects you provided to format().

Doing this would be a tremendous help!

@crosser
Copy link
Author

crosser commented Oct 31, 2022

pylint produces a crash report, and shows the link in your terminal, like this:

No, not really, it does not. I am attaching a (censored) stderr from running the test. The line in the source code that apparently triggers the problem is pretty innocuous:

    @property
    def vnet_id(self):  # <---- this is the line 266 that is mentioned in the "Exception on node" message
        if ...:

There is very similar property definition right before this one, that does not trigger the problem.

pyerr.txt

Pylint command was python3 -m pylint --jobs=0 --rcfile=test/style/pylint.conf <project-dir>

$ pylint --version
pylint 2.15.5
astroid 2.12.12
Python 3.10.8 (main, Oct 24 2022, 10:07:16) [GCC 12.2.0]

edit:

enough surrounding code to rebuild the objects you provided to format().

I did not provide any objects to format(), astroid did...

@jacobtylerwalls
Copy link
Member

Thanks for providing the traceback.

No, not really, it does not. I am attaching a (censored) stderr from running the test.

I see now that it's because you're invoking pylint from a unittest, so your test is managing the output.

The line in the source code that apparently triggers the problem is pretty innocuous:

The deeper failure is on the call in line 268, not the function def on line 266. Is there anything you can sanitize and tell us about line 268? Thanks again for providing the help.

@crosser
Copy link
Author

crosser commented Oct 31, 2022

I see now that it's because you're invoking pylint from a unittest, so your test is managing the output.

When I run pylint by hand

pylint --jobs=0 --rcfile=test/style/pylint.conf <module-name> | tee /tmp/pyerr.txt

there is still no "Fatal error while checking ..." message in the output

The line in the source code that apparently triggers the problem is pretty innocuous:

The deeper failure is on the call in line 268, not the function def on line 266. Is there anything you can sanitize and tell us about line 268? Thanks again for providing the help.

Oh yes, there is a something.format() in that line! But the "something" is a literal string:

    @property
    def vnet_id(self):
        if self.backend == "something":
            return "{:04x}{:04x}n{:d}".format(  # <---- this is line 268
                self.<some-attr>, self.<another-attr>, self.<third-attr>
            )
        if self.backend == "somethingelse":
            return "h{:08}n{:d}".format(self.<more-attr>, self.<and more>)
        return None

@jacobtylerwalls
Copy link
Member

Thanks, that was very helpful. Here is a reproducer:

x = "{:c}".format(None)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants