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

defined_names doesn't show all definitions, repr fails for `self` definitions #1411

Closed
mpanarin opened this issue Sep 26, 2019 · 9 comments
Closed

Comments

@mpanarin
Copy link

@mpanarin mpanarin commented Sep 26, 2019

easy to reproduce with this snippet. Change to your filepath obviously:

import jedi  # 0.15.1

DOC = """
class B:
    def __init__(self):
        self.z = 5
"""
DOC_URI = "file:///home/m-panarin/Desktop/test_files/reproduce_jedi/file.py"


if __name__ == '__main__':
    # will contain 4 definitions: class B, def __init__, self, z
    all_names = jedi.api.names(
        source=DOC,
        path=DOC_URI,
        definitions=True,
        all_scopes=True,
        references=False,
    )
    assert all_names[-1].name == "z"
    assert all_names[-1].parent().name == "__init__"
    # so __init__ is a parent of z
    # BUUUUUUT

    assert all_names[1].name == "__init__"
    # this fails as it only contains 'self'
    assert sorted([x.name for x in all_names[1].defined_names()]) == sorted(["self", "z"])

    # another issue I found: repr fails for `self` definitions
    # this print will trigger an exception
    # print(all_names[1].defined_names())
@davidhalter
Copy link
Owner

@davidhalter davidhalter commented Sep 30, 2019

Why is this an issue class B, def __init__, self, z?

Also for the other issues you found, please describe them clearer and post a traceback if there are exceptions. It's easier to fix them this way. Thanks!

@mpanarin
Copy link
Author

@mpanarin mpanarin commented Oct 6, 2019

Sorry for the late reply.

  1. The issue is that defined_names doesn't list z. Although, __init__ is considered a parent.
    this is a problem when trying to use jedi for building hierarchical tree of symbols in document for LSP. To get z in symbols list I need to get all symbols and then build the tree from flat list for bottom up. Which is inconvenient.

  2. About the traceback:

Traceback (most recent call last):
  File "file.py", line 31, in <module>
    print(all_names[1].defined_names())
  File "/home/m-panarin/.virtualenvs/pyls/lib/python3.7/site-packages/jedi/api/classes.py", line 376, in __repr__
    self.description,
  File "/home/m-panarin/.virtualenvs/pyls/lib/python3.7/site-packages/jedi/api/classes.py", line 551, in description
    return typ + ' ' + self._name.to_string()
AttributeError: 'TreeNameDefinition' object has no attribute 'to_string'

Inferior Python exited abnormally with code 1 at Sun Oct  6 14:00:28

You can reproduce it with the snippet above if you uncomment the last line.

@davidhalter davidhalter added the bug label Oct 7, 2019
@davidhalter
Copy link
Owner

@davidhalter davidhalter commented Dec 6, 2019

I seem to have fixed the traceback. The other issue still exists.

Thanks again for the reproduction steps. That really helps a ton. I just tried to reproduce 3 other issues that I couldn't, which is a bit frustrating.

@davidhalter
Copy link
Owner

@davidhalter davidhalter commented Dec 12, 2019

I wrote a test and then realized that this is actually about a self name. This should probably be changed, but it's quite a bit harder than I initially thought. Therefore not a high priority.

def test_defined_param_names(names):
    code = dedent("""
        class B:
            def __init__(self):
                self.z = 5
        """)

    # Will contain 4 definitions: class B, def __init__, self, z
    all_names = names(
        code,
        definitions=True,
        all_scopes=True,
        references=False,
    )
    assert all_names[-1].name == "z"
    assert all_names[-1].parent().name == "__init__"

    assert all_names[1].name == "__init__"
    assert sorted([x.name for x in all_names[1].defined_names()]) == sorted(["self", "z"])
@davidhalter
Copy link
Owner

@davidhalter davidhalter commented Dec 28, 2019

@mpanarin Does it makes sense for you if other side effects are also listed? IMO that's the only thing that makes sense. Say someone your code writes sys.path = []. That would also be a definition, right?

@mpanarin
Copy link
Author

@mpanarin mpanarin commented Dec 28, 2019

@mpanarin Does it makes sense for you if other side effects are also listed? IMO that's the only thing that makes sense. Say someone your code writes sys.path = []. That would also be a definition, right?

This does make sens, yes. Is there any possibility to easily narrow it down on the client side after?
Something like side-effect parameter to differentiate would be great, but definitely not an obligatory thing.

@davidhalter
Copy link
Owner

@davidhalter davidhalter commented Dec 28, 2019

For now there's probably nothing like this. If anything self modifications would also be side effects.

@davidhalter
Copy link
Owner

@davidhalter davidhalter commented Jan 2, 2020

Decided that it might make sense to make this possible in the future, but it's really a new type of definition or as I said a side effect and should be listed as such. Therefore a new feature, not a bug.

@davidhalter
Copy link
Owner

@davidhalter davidhalter commented Feb 4, 2020

I added is_side_effect to definition. This means that you have to use names(references=True) and then filter with definition.is_side_effect(). IMO this is the best way to do this for now.

Will be part of the 0.17.0 release.

@davidhalter davidhalter closed this Feb 4, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Linked pull requests

Successfully merging a pull request may close this issue.

None yet
2 participants
You can’t perform that action at this time.