python-language-server gets its whole default feature set from one pinned dependency
An implementation of the Language Server Protocol for Python
At a glance
- What is it?
- palantir's python-language-server implements the Language Server Protocol for Python 2.7 and 3.5+, and six of its eight advertised features come from a single package held below jedi 0.18.0. Two more need optional providers, and workspace files outrank the settings your editor sends.
- Who is it for?
- Adopt python-language-server knowing that its free features and its dependency floor are one decision: jedi>=0.17.2,<0.18.0 is what delivers completions, definitions, hover, references, signature help and symbols, and pip has to satisfy that ceiling before anything else.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 31 days ago.
- What is it written in?
- Mainly Python, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on November 14, 2026, and from our analysis. They are not legal advice.
Star history
- palantir/python-language-server2,702 ★ · -2
| Repository | 2026-10-04 | 2026-11-14 |
|---|---|---|
| palantir/python-language-server | 2.7k | 2.7k |
-2 Stars in the last 41 days, measured from the daily GitHub snapshot. Compare with other projects
Editorial analysis
One dependency supplies the default feature set, and it is pinned below 0.18.0
Six of the capabilities the README advertises come out of a single package. Completions, Definitions, Hover, References, Signature Help and Symbols are all provided by Jedi, and the installation section states that the base language server requires Jedi for exactly that list. The version it asks for is where the packaging gets opinionated: install_requires carries jedi>=0.17.2,<0.18.0, an upper bound rather than the open range most dependencies receive.
That ceiling decides more than a version number. It is the entire default install, so pip pulls an older Jedi into a clean environment, and in an environment where something else already needs a newer Jedi the two requirements cannot both hold, which is where resolver backtracking on this package tends to come from. The line carries no comment and no issue reference, so nothing in the packaging file says what changed above 0.18 or whether the ceiling is still needed.
The remaining runtime dependencies are few: python-jsonrpc-server>=0.4.0 and pluggy are the only unconditional ones, while configparser, future, backports.functools_lru_cache and the two ujson lines all sit behind python_version markers for old interpreters. Two thirds of install_requires is compatibility scaffolding, and the one entry that governs what you can actually do is the bounded one.
Workspace configuration overrides the settings your editor sends
Three layers decide a setting, and they are ordered from least specific to most specific in a direction that surprises people: user configuration in the home directory, then configuration passed in by the language client, then configuration discovered in the workspace. The workspace layer wins, so a value your editor passes to the server can be overruled by a file sitting in the repository you opened.
Only two source families exist. pycodestyle is discovered in ~/.config/pycodestyle, setup.cfg, tox.ini and pycodestyle.cfg. flake8 is discovered in ~/.config/flake8, setup.cfg, tox.ini and flake8.cfg. The default source is pycodestyle, and assigning ['flake8'] to pyls.configurationSources switches to the other one.
The two lists differ in exactly two places: the folder name under the home directory and the standalone cfg file at the end. setup.cfg and tox.ini appear in both lists, so a project that relies on those two files is read either way, and the switch is about which standalone file and which home directory folder get read, not about the shared ones. Where to look for a full option list is also unusual: the README points at vscode-client/package.json rather than at a documentation page, so the editor extension directory is where the configuration surface is defined.
Eight features are listed, six ship by default, and formatting ships with nothing
The Language Server Features section walks through eight capabilities with a recording for each: auto completion, code linting with pycodestyle and pyflakes, signature help, go to definition, hover, find references, document symbols and document formatting. Six of those are the Jedi set. Code linting is not in the base install at all, since pycodestyle and pyflakes are both optional providers, which means a plain pip install gives you a server that navigates and completes but reports nothing about style or errors. Document formatting is the same story with one more step, because formatting needs autopep8 or YAPF and neither is installed by default.
Docstring linting runs the other way. pydocstyle is an optional provider that is disabled by default, so installing it does not turn it on; the setting has to be enabled in your LSP configuration:
"pyls.plugins.pydocstyle.enabled": trueThat is the only provider toggle the repository shows anywhere, and it is the one provider that needs opting in. The other six, including both linters and both formatters, switch on by being present. So of eight advertised features, a stock install delivers six, one needs a package plus a flag, and one needs a package plus a preference between two of them.
Providers switch on by being installed, and the all extra turns on all of them
The rule the installation section gives is presence based: if the respective dependencies are found, the following optional providers will be enabled. Rope covers completions and renaming, Pyflakes detects various errors, McCabe checks complexity, pycodestyle checks style, pydocstyle checks docstring style, and autopep8 and YAPF both format. No configuration key is documented for switching a found provider off, so what happens is decided by what is installed rather than by what you asked for.
That makes the extras syntax a behaviour change rather than a convenience. Installing one provider adds it:
pip install 'python-language-server[yapf]'Installing all of them adds every provider in one step:
pip install 'python-language-server[all]'An [all] install therefore runs two linters, a complexity check, a style check, a docstring check where it has been enabled, and two formatters inside one server process. Where autopep8 and YAPF are both present, the README states that YAPF is preferred over autopep8, so the [all] install settles the formatting conflict in favour of YAPF without asking which one you meant. The plugin approach extends the same pattern: pyls-mypy, pyls-isort and pyls-black are separate distributions that plug in through pluggy, each bringing its own checker or formatter into the environment that already has a bounded Jedi requirement to satisfy.
Three releases in nine days at the end of 2020, and commits long after
The release history stops. Three tags are recorded: 0.36.0 on 2020-11-03, 0.36.1 on 2020-11-08 and 0.36.2 on 2020-12-11, nine days of shipping and then nothing further. The repository is not archived, and the most recent push is dated 2026-07-06, so work has continued on the branch for years after the last tagged build.
That split matters for how you install. setup.py takes its version from versioneer.get_version(), which derives it from the checkout and its tags rather than from a hardcoded string, and versioneer.py sits at the repository root to do it. A version reported after installing from source therefore need not read 0.36.2, while an install from a package index only ever gets that build. Anyone comparing versions to decide whether two installations match has to account for which route produced them.
The README also mixes two branch names. The default branch is develop, the feature recordings are fetched from develop, and the licence badge points at the master branch, so the badges on the page are not all describing the branch you would clone by default.
Editor integrations live in separate packages, one feature each
The integration story is deliberately thin here and spread across other repositories. Three plugins are named: pyls-mypy for Mypy type checking on Python 3, pyls-isort for Isort import sorting, and pyls-black for formatting through Black. Each is its own distribution with its own release cadence, and the server itself depends on pluggy, which is what lets them attach.
The guidance for extending it points outward twice. Look at those plugin repositories for examples of how to write a plugin, and file an issue here if you need assistance writing one. So the extension contract is documented in other projects, and this repository carries no configuration keys for the plugins it names, only their project pages.
One consequence is worth planning for. Pinning the server does not pin any of the three plugins, and each one brings its own formatter or type checker into the same environment as the bounded Jedi requirement, so the resolver is handed more constraints than the base install presents. The plugin route also inherits the presence rule: an installed plugin is an active one, with the documented exception being pydocstyle, which arrives disabled until you set the flag yourself.
Testing takes the test extra, and interactive debugging needs a Node toolchain
The development section keeps the test suite to one line:
pip install .[test] && pytestThe distribution leaves the tests behind on purpose, since find_packages is called with exclude=['contrib', 'docs', 'test', 'test.*'], so an installed copy carries the server and not its test tree. Two of those excluded names, contrib and docs, are not present in the repository root at all. The root does hold .coveragerc and .pylintrc for the checks pytest and lint runs pick up, plus MANIFEST.in and a scripts directory.
Interactive debugging goes through VS Code rather than through the Python side. The documented flow is virtualenv env, then . env/bin/activate, then pip install ., then cd vscode-client, then yarn install, and finally yarn run vscode -- $PWD/../ to launch an editor configured to use this server. From there the server's output appears under View then Output with pyls in the dropdown, and Cmd + r refreshes the window. That makes a Node toolchain and an editor checkout the path for stepping through the server, and it is also why vscode-client/package.json is named as the home of the full configuration option set.
Editorial conclusion
Adopt python-language-server knowing that its free features and its dependency floor are one decision: jedi>=0.17.2,<0.18.0 is what delivers completions, definitions, hover, references, signature help and symbols, and pip has to satisfy that ceiling before anything else. Verify two things on your own setup before you point an editor at it, which is where setup.cfg and tox.ini can quietly override what your client sends, and what happens when the plugins you want bring their own formatter or type checker into the same environment. If you need a formatter, name one, since YAPF and autopep8 are both optional and YAPF wins when both are present.
Frequently asked questions
how to install python language server
The base install is pip install python-language-server, with extras added for providers, for example pip install 'python-language-server[yapf]' or pip install 'python-language-server[all]'. If pip reports that 'install_requires' must be a string or list of strings, the fix given is pip install -U setuptools before retrying.
what is python language server
It is an implementation of the Language Server Protocol for Python 2.7 and 3.5+. The base install depends on Jedi for Completions, Definitions, Hover, References, Signature Help and Symbols, while linting and formatting come from optional providers that have to be installed.
How do I restart the Python language server in VS Code?
The repository documents no restart command or procedure. Its editor notes say to open View then Output, where pyls appears in the dropdown, and to press Cmd + r to refresh VS Code.
Does python-language-server still support Python 2.7?
It is described as a Python 2.7 and 3.5+ implementation, and setup.py keeps environment markers for old interpreters: configparser below 3.0, future>=0.14.0 below 3, backports.functools_lru_cache below 3.2, and ujson<=2.0.3 on non-Windows Python 2 against ujson>=3.0.0 on Python 3.
Is python-language-server the same as Pylance?
No relationship to Pylance is stated anywhere in the repository. Its Jedi dependency is pinned to >=0.17.2,<0.18.0, and the editor integrations it names are separate pyls-mypy, pyls-isort and pyls-black plugin packages.
Which code formatter does python-language-server use?
autopep8 and YAPF are both optional providers, and YAPF is stated to be preferred over autopep8. Neither arrives with the base install, and installing 'python-language-server[all]' pulls both in, with YAPF taking precedence.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/palantir-python-language-server)Star history chart for your README
[](https://hysenlabs.com/projects/palantir-python-language-server)Was this useful?