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

Improve module loading path handling at completion, liinting, and so on #712

Open
wants to merge 10 commits into
base: develop
Choose a base branch
from

Conversation

flying-foozy
Copy link

BTW, the 3rd commit in this series ("Introduce pyls.extraSysPath configuration") will cover pull request #382

@palantirtech
Copy link
Member

Thanks for your interest in palantir/python-language-server, @flying-foozy! Before we can accept your pull request, you need to sign our contributor license agreement - just visit https://cla.palantir.com/ and follow the instructions. Once you sign, I'll automatically update this pull request.

@ccordoba12
Copy link
Contributor

the 3rd commit in this series ("Introduce pyls.extraSysPath configuration") will cover pull request #382

Please remove that because it was implemented in PR #680.

@flying-foozy
Copy link
Author

the 3rd commit in this series ("Introduce pyls.extraSysPath configuration") will cover pull request #382

Please remove that because it was implemented in PR #680.

Such extra paths will be needed also at spawning pylint process, in order to avoid unintentional "import-error" for libraries installed there.

Then, which one is suitable ?

  1. use plugins.jedi.extra_paths also for pylint plugin
  2. introduce new plugins.pylint.extra_paths for pylint plugin
  3. keep pyls.extraSysPath for common extra sys path configuration shared between plugins

BTW, I noticed that 'Introduce config source for "pyls"' commit in this series is not correct enough.

Therefore, please do not merge this pull request as it is, even if keeping pyls.extraSysPath was suitable. I'll revise that commit.

@ccordoba12
Copy link
Contributor

use plugins.jedi.extra_paths also for pylint plugin

Please use this one to only have one setting about it.

@ccordoba12 ccordoba12 changed the title Improve module loading path handling at completion, liint-ing, and so on [WIP] Improve module loading path handling at completion, liinting, and so on Dec 31, 2019
@flying-foozy
Copy link
Author

Oops, I overlooked test failures on Windows, sorry.
I'm working to fix them, and will soon re-push revised series.

At getting the value in nested settings dict, newly added
get_config_by_path() is more efficient and readable than "get with
empty dict" chain like below, which is sometimes used in current
implementation.

  settings.get("foo", {}).get("bar", {}).get("baz")
Before this commit, 'setup.py' or 'pyproject.toml' should be created
to specify source root(s) other than the workspace root, even if such
file is not actually needed.

In order to explicitly specify source root(s) in the workspace, this
commit introduces pyls.source_roots configuration, and makes
workspace.source_roots() return its value if configured.

Path in pyls.source_roots is ignored, if it refers outside of the
workspace.

This configuration is also useful in the case that the workspace
consists of multiple (independent) services and a library shared by
them, for example. In such case, N + 1 source roots are listed in
pyls.source_roots configuration.

BTW, this commit puts some utilities into _util.py for reuse in the
future. Especially, os.path.commonprefix() for checking inside-ness in
find_parents() below should be replaced with is_inside_of(), because
the former returns unintentional value in some cases.

    if not os.path.commonprefix((root, path)):
        log.warning("Path %s not in %s", path, root)
        return []

For example:

  - commonprefix(('/foo', '/bar')) returns not false value but '/'
  - commonprefix(('/foo', '/foobar')) returns not false value but '/foo'
This is useful to specify source roots in relative path, if pyls
process might run in other than the root of the target workspace(s).
Before this commit, plugins.jedi.extra_paths configuration is used
only at execution of jedi.Script in Document.jedi_script().

Therefore, at spawning a process for other plugins (e.g pylint), such
extra paths are ignored. It might causes unintentional failure of
finding out libraries installed into those locations, even though Jedi
can find out.

After this commit, just using Document.sys_path() instead of sys.path
is enough path configuration for any plugins.
Before this commit, plugins.jedi.extra_paths can be configured only
via Language Server Protocol didChangeConfiguration method.

This is inconvenient, if:

  - it is difficult to issue LSP didChangeConfiguration method with
    per-workspace configuration

  - such configuration should be persisted inside workspace

This commit reads plugins.jedi.extra_paths configuration also from
project-level configuration "setup.cfg" and "tox.ini".
This is the preparation for spawning pylint process with pyls specific
customization in subsequent change.

Almost all of spawn_pylint is cited from pylint/epylint.py in
6d818e3b84b853fe06f4199eb8408fe6dfe033be (the latest version on master
branch at 2019-12-04) of pylint.

BTW, this commit imports StringIO manually for compatibility between
Python 2.x and 3.x instead of using "six" like recent pylint 1.9.x
(supporting python 2.x), because requiring "six" only for StringIO
seems over-kill.
For example, jedi respects VIRTUAL_ENV environment variable at finding
out libraries. Therefore, (virtualenv) runtime for pyls/jedi can be
separated from one for the target workspace.

On the other hand, pylint does not respect VIRTUAL_ENV, and might
cause unintentional "import-error" (E0401) for libraries installed in
such virtualenv, even though jedi can recognize them.

In order to make pylint respect libraries installed into extra
paths, this commit uses Document.sys_path() instead of sys.path of
current pyls process, at spawning pylint.

At this commit, Document.sys_path() should respect source roots in the
workspace, VIRTUAL_ENV, PYTHONPATH, and plugins.jedi.extra_paths
configuration.
This commit describes about not only features added by previous
commits but also some underlying specifications.
@flying-foozy
Copy link
Author

I re-pushed revised version of this series.

@flying-foozy flying-foozy changed the title [WIP] Improve module loading path handling at completion, liinting, and so on Improve module loading path handling at completion, liinting, and so on Feb 9, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants