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

No definitions found for certain scenario #880

Closed
dmalyuta opened this issue Mar 1, 2017 · 10 comments
Closed

No definitions found for certain scenario #880

dmalyuta opened this issue Mar 1, 2017 · 10 comments
Labels

Comments

@dmalyuta
Copy link

dmalyuta commented Mar 1, 2017

Please see a detailed description and discussion in tkf/emacs-jedi#281, which turns out to be probably a Jedi issue. In brief:

  1. Clone this repository: git clone https://github.com/ethz-asl/kalibr
  2. Go to line 49 and try to find definitions of addDesignVariables. No definitions are found, yet the addDesignVariables function is defined in IccSensors.py, which is a python file in the same directory.

Here is a Python console session showing the fault (courtesy syohex - which shows that I'm not the only one affected):

% ipython
Python 2.7.10 (default, Oct 23 2015, 19:19:21)
Type "copyright", "credits" or "license" for more information.

IPython 5.1.0 -- An enhanced Interactive Python.
?         -> Introduction and overview of IPython's features.
%quickref -> Quick reference.
help      -> Python's own help system.
object?   -> Details about 'object', use 'object??' for extra details.

In [1]: import jedi

In [2]: source = open('IccCalibrator.py', 'r').read()

In [3]: script = jedi.Script(source, 49, len('        self.CameraChain.'), 'IccCalibrator.py')

In [4]: defs = script.goto_definitions()

In [5]: defs
Out[5]: []

I am running Ubuntu 14.04 and:

$ pip show jedi
---
Name: jedi
Version: 0.10.0
Location: /usr/local/lib/python2.7/dist-packages
Requires: 
$ pip show python
---
Name: Python
Version: 2.7
Location: /usr/lib/python2.7/lib-dynload
Requires: 

Since line 177 calls the registerCamChain function with camChain (an IccCameraChain object) argument, Jedi should make the guess that self.CameraChain is an IccCameraChain object and thus should be able to find the definition of addDesignVariables on line 49, which is a method of the IccCameraChain class.

@davidhalter
Copy link
Owner

davidhalter commented Mar 1, 2017

No definitions are found, yet the addDesignVariables function is defined in IccSensors.py, which is a python file in the same directory.

The problem is not that it wouldn't find addDesignVariables. The problem is that it doesn't find the execution of registerCamChain (which is something I also cannot find).

@dmalyuta
Copy link
Author

dmalyuta commented Mar 1, 2017

Why did you close this? In the last paragraph of my original post, I say: line 177 calls the registerCamChain function with camChain (an IccCameraChain object) argument. So it should be finding the execution of registerCamChain, right?

@davidhalter
Copy link
Owner

Hmm ok. I see. I still think that this is quite hard to understand. I'm reopening. However inheritance is hard to understand, if you want to do it right.

IMO this kind of code can be

Sorry for closing prematurely and not reading your issue fully, because the description was actually good. I just tend to close aggressively to keep the tracker clean (and my limited time resources down).

@dmalyuta
Copy link
Author

dmalyuta commented Mar 2, 2017

IMO this kind of code can be

Could you please finish your sentence here?

Here is a simpler example of the same problem, where Jedi fails to find the definition based on context elsewhere in the project of where/with what type of arguments the function is called:

.
├── foo_module
│   ├── __init__.py
│   ├── MyCalibrator.py
│   ├── MySensor.py
│   └── MyUtil.py
└── main.py

__init__.py:

from MyCalibrator import *
import MyUtil as util
import MySensor as sens

MyCalibrator.py:

def Calibrate(sensor):
    sensor.calibrate()

MySensor.py:

import MyUtil as utils

class Sensor:
    def calibrate(self,arg):
        arg.Hello()
        print("Calibrating the sensor now!")

MyUtil.py:

def Hello():
    print("Hello World!")

class Bar:
    def Hello(self):
        print("Bar says hi!")

main.py:

from foo_module import *

util.Hello()

barObject=util.Bar()

sens.Sensor().calibrate(barObject)

Jedi fails to find definition of the Hello method in MySensor.py:

~/.../foo_module $ ipython
Python 2.7.6 (default, Oct 26 2016, 20:30:19) 
Type "copyright", "credits" or "license" for more information.

IPython 1.2.1 -- An enhanced Interactive Python.
?         -> Introduction and overview of IPython's features.
%quickref -> Quick reference.
help      -> Python's own help system.
object?   -> Details about 'object', use 'object??' for extra details.

In [1]: import jedi

In [2]: source = open('MySensor.py','r').read()

In [3]: script = jedi.Script(source, 7, len('        arg.'), 'MySensor.py')

In [4]: defs = script.goto_definitions()

In [5]: defs
Out[5]: []

@davidhalter
Copy link
Owner

Sorry again.

IMO this kind of code can be understood, but I'm not sure it will be in the next one or two years. Understanding this form of inheritance is possible, but it's hard to implement and I have other plans currently. I'll leave it open however.

If anyone (you?) wants to look into this, the jedi.evaluate.dynamic module needs to be slightly changed to search for inherited class calls as well and not only calls to inherited classes.

~ Dave

@dmalyuta
Copy link
Author

dmalyuta commented Mar 3, 2017

I see. Is this kind of functionality not really useful to professional Python developers (I'm new to the language), that it is something you don't see as being urgent to implement? What do you use when writing Python to quickly and efficiently call functions/methods which (like in this example) you can't autocomplete/immediately jump to definitions of?

@davidhalter
Copy link
Owner

Well, I guess for "professionals" there's other issues that are more important. Among the issues are lacking virtuelenv support, lacking Django support and so on. I think the case you mentioned is something that is not very typical for Python. I also think that it's not a good pattern to change the state in such a function (and therefore probably nobody ever had that issue before).

@dmalyuta
Copy link
Author

dmalyuta commented Mar 4, 2017

change the state in such a function

What do you mean?

@davidhalter
Copy link
Owner

    def registerCamChain(self, sensor):
        self.CameraChain = sensor

This is usually a bad idea. It should be part of the instance creation call, IMO.

@davidhalter
Copy link
Owner

I realized that the only way we would ever fix that is by implementing #1059.

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

No branches or pull requests

2 participants