yt-project / unyt

Handle, manipulate, and convert data with units in Python
https://unyt.readthedocs.io
BSD 3-Clause "New" or "Revised" License
364 stars 48 forks source link

PyCharm IDE cannot find references to unit classes #142

Open jamesbraza opened 4 years ago

jamesbraza commented 4 years ago

Description

Since unit instances are added to unyt's namespace at runtime, PyCharm (Python IDE) cannot introspect the attributes of a given unit. PyCharm declares "Cannot find reference".

I would like to be able to use PyCharm's introspection to aid in developer speed (code completion) and decrease the chances of attribute errors.

Possible solution: this question suggests making a stub file. I am not sure if this is feasible.

What I Did

See this question on Stack Overflow.

from unyt import degC

t1 = 0 * degC
t1.convert_to_base()

image

ngoldbaum commented 4 years ago

I wonder if we dynamically created an __all__ attribute at import time, would PyCharm be able to resolve the references then? I don't have PyCharm installed so can't really help much with debugging this one.

If PyCharm is doing this purely using text analysis then I don't think there's much we can do. We're definitely not going to go to explicitly listing everything since that would be a maintainance nightmare.

JBorrow commented 4 years ago

This is also a problem in Visual Studio Code, IIRC.

jamesbraza commented 4 years ago

@JBorrow what do you do? Just ignore it? Do you ever use code completion with unit instances?

@ngoldbaum I installed unyt and inserted __all__ = ["degC"] into unyt.__init__.py.

The result is my base Python file now no longer complains "Cannot find reference", it now knows that degC comes from unyt. However, it still doesn't know that degC is a Unit instance. PyCharm just suggests that it's an object. It does not suggest the method .copy or the property .units while typing.

ngoldbaum commented 4 years ago

Another idea that might work is to generate __init__.py at build time (e.g. orchestrated by setup.py) and replace the globals manipulation with code literals.

JBorrow commented 4 years ago

@JDusub83

I in general just ignore this, yes. Usually I am working inside a function with type hints:

image

The red underline is telling me that Mpc is not found in unyt.

jamesbraza commented 4 years ago

Back to the __all__ approach. Adding a global variable type annotation on the units right after __all__ solves the problem... PyCharm can now infer the type!

Inside unyt.__init__.py:

__all__ = ["degC"]
degC: Unit

I am unsure which is better. Does anyone have any thoughts?

ngoldbaum commented 4 years ago

Is it possible to dynamically define type annotations? If so, does PyCharm recognize those? It's also not clear to me from your examples that PyCharm would know how to deal with a dynamically defined __all__.