Jeff Nyman
Jeff Nyman

Reputation: 890

PyCharm Warnings and Expected Types: When To Care?

There are so many posts and questions about PyCharm and warnings and yet there seems to be very little consensus on when PyCharm is actually telling you something useful and when it's not, particularly regarding "expected types" warnings. Posting to the IntelliJ / PyCharm support boards often doesn't provide much of a roadmap, I'm finding.

So I kept the title of this question a bit generic but I'll provide a very specific example with two different warnings, where fixing one leads to an error in execution. I'm hoping there is perhaps a general answer for this class of warning. Perhaps the answer is just that PyCharm isn't very good at this kind of detection.

Context

So consider here the following code:

def load_agent(pacman, no_graphics):
  python_path_string = os.path.expandvars("$PYTHONPATH")

  if python_path_string.find(';') == -1:
    python_path_dirs = python_path_string.split(':')
  else:
    python_path_dirs = python_path_string.split(';')

  python_path_dirs.append('.')

  for module_dir in python_path_dirs:
    if not os.path.isdir(module_dir):
        continue

    module_names = [f for f in os.listdir(module_dir) if f.startswith('agents_')]

There is more code in my for block but it's not relevant to the issue here. I'll also say my code does work. But my concern is whether or not I should ignore warnings about types.

The Problems

I'll start with the last line. If you try to do anything odd with what you pass startswith() at the Python REPL you are told:

startswith first arg must be str or a tuple of str, not bytes

Makes sense. So then why does PyCharm say the following about this line (the 'agents_' argument, specifically:

Expected type 'Union[bytes, Tuple[bytes, ...]], got 'str' instead

Further, line 9 above (python_path_dirs.append('.')) provides a PyCharm warning as well (for the '.', specifically):

Expected type 'bytes' (matched generic type '_T'), got 'str' instead

Solution Attempts

For the issue on line 9, I know I can put a b in front of the string. Doing so however causes other problems. Specifically, it causes an execution problem in the last line (the one that I initially mentioned).

So to be clear: the code above, as is, works fine. If I assume PyCharm is warning me correctly, I fix line 9 so that it looks like this:

python_path_dirs.append(b'.')

That is advice provided by the IntelliJ / PyCharm team and I see that in a few other StackOverflow answers as well.

Doing that, however, causes the last line in my code above to fail with this error:

TypeError: startswith first arg must be bytes or a tuple of bytes, not str

Color Me Conflicted

So my concern is that the two lines seem "connected" in that they both get warnings. And trying to satisfy the first warning leads to an execution error in the second line. Yet the warnings are clearly speaking of different types. Further, the warning for the last line seems to be contradicting what Python itself says it expects as an argument for startswith().

I realize an answer could be: "If your code works, what's the problem?" But part of the issue is that I want to trust the tools I use for development. If I start turning off warnings or just assume all is good, contrary to the tool, I may as well not use the tool.

Upvotes: 2

Views: 1099

Answers (1)

SteveJ
SteveJ

Reputation: 3323

I don't work for Jet Brains, but I have used Resharper and PyCharm for many years. Here is my general experience/thoughts on the subject (specifically for Pycharm).

Until recently, with the availability of type hints 3.5+, PyCharm has had to make some really clever inferences to provide things like type checking and auto complete. It does a pretty dang good job considering -- but often its best guess simply isn't correct. Ultimately sometimes only the developer can decide if it simply guessed wrong.

If you are like me, you can't stand seeing those little curly lines telling you of a code smell. Fortunately, PyCharm gives you the ability to turn off a warning for a line, a function, or even a file (eg. # noinspection PyTypeChecker - in your case). When I know that PyCharm is giving me wrong warnings, I rely on those. Sometimes I disagree with PyCharm altogether and adjust checks for the entire project.

Now, with type hinting this should get a lot better (provide developers use it). PyCharm will have more reliable information on which to make its decisions. The good news is that you can help.

  1. Ensure that you use type hinting for all your personal projects
  2. Encourage others that you work with to do the same
  3. Kindly and positively encourage package maintainers to do the same
  4. Offer to contribute to projects by adding type hints

If every developer does the above, most of your false warnings go away. Until then, there is no magic answer for all. You simply have to deal with warnings on a case by case basis.

Upvotes: 1

Related Questions