Skip to content

Commit

Permalink
Merge branch 'master' into deprecations
Browse files Browse the repository at this point in the history
  • Loading branch information
davidhalter committed Dec 12, 2020
2 parents bb303a7 + 42a759a commit f9cec89
Show file tree
Hide file tree
Showing 79 changed files with 593 additions and 204 deletions.
14 changes: 14 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
root = true

[*]
charset = utf-8
end_of_line = lf
indent_style = space
insert_final_newline = true
trim_trailing_whitespace = true

[*.py]
indent_size = 4

[*.md]
indent_size = 2
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,5 @@ jedi.egg-info/
record.json
/.cache/
/.pytest_cache
/.mypy_cache
/venv/
2 changes: 2 additions & 0 deletions .readthedocs.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
python:
pip_install: true
19 changes: 13 additions & 6 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,15 @@ python:

env:
- JEDI_TEST_ENVIRONMENT=38
- JEDI_TEST_ENVIRONMENT=39
- JEDI_TEST_ENVIRONMENT=37
- JEDI_TEST_ENVIRONMENT=36
- JEDI_TEST_ENVIRONMENT=interpreter

matrix:
include:
- python: 3.8
script:
script:
- 'pip install coverage'
- 'coverage run --source jedi -m pytest'
- 'coverage report'
Expand All @@ -30,8 +31,8 @@ matrix:
install:
- 'pip install .[qa]'
script:
# Ignore F401, which are unused imports. flake8 is a primitive tool and is sometimes wrong.
- 'flake8 --extend-ignore F401 {posargs:jedi}'
- 'flake8 jedi setup.py'
- 'mypy jedi sith.py'
install:
- sudo apt-get -y install python3-venv
- pip install .[testing]
Expand All @@ -47,9 +48,15 @@ script:
# Only required for JEDI_TEST_ENVIRONMENT=38, because it's not always
# available.
download_name=python-$test_env_version
wget https://s3.amazonaws.com/travis-python-archives/binaries/ubuntu/16.04/x86_64/$download_name.tar.bz2
sudo tar xjf $download_name.tar.bz2 --directory / opt/python
ln -s "/opt/python/${test_env_version}/bin/python" /home/travis/bin/$python_bin
if [ "$JEDI_TEST_ENVIRONMENT" == "39" ]; then
wget https://storage.googleapis.com/travis-ci-language-archives/python/binaries/ubuntu/16.04/x86_64/python-3.9-dev.tar.bz2
sudo tar xjf python-3.9-dev.tar.bz2 --directory / opt/python
ln -s "/opt/python/3.9-dev/bin/python" /home/travis/bin/python3.9
else
wget https://s3.amazonaws.com/travis-python-archives/binaries/ubuntu/16.04/x86_64/$download_name.tar.bz2
sudo tar xjf $download_name.tar.bz2 --directory / opt/python
ln -s "/opt/python/${test_env_version}/bin/python" /home/travis/bin/$python_bin
fi
elif [ "${python_path#/opt/pyenv/shims}" != "$python_path" ]; then
# Activate pyenv version (required with JEDI_TEST_ENVIRONMENT=36).
pyenv_bin="$(pyenv whence --path "$python_bin" | head -n1)"
Expand Down
2 changes: 2 additions & 0 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ Unreleased
- Functions with ``@property`` now return ``property`` instead of ``function``
in ``Name().type``
- Started using annotations
- Better support for the walrus operator
- Project attributes are now read accessible

This is likely going to be the last minor release before 1.0.

Expand Down
7 changes: 7 additions & 0 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -52,9 +52,16 @@ Jedi can currently be used with the following editors/projects:
- wdb_ - Web Debugger
- `Eric IDE`_ (Available as a plugin)
- `IPython 6.0.0+ <https://ipython.readthedocs.io/en/stable/whatsnew/version6.html>`_
- `xonsh shell <https://xon.sh/contents.html>`_ has `jedi extension <https://xon.sh/xontribs.html#jedi>`_

and many more!

There are a few language servers that use Jedi:

- `jedi-language-server <https://github.com/pappasam/jedi-language-server>`_
- `python-language-server <https://github.com/palantir/python-language-server>`_
- `anakin-language-server <https://github.com/muffinmad/anakin-language-server>`_

Here are some pictures taken from jedi-vim_:

.. image:: https://github.com/davidhalter/jedi/raw/master/docs/_screenshots/screenshot_complete.png
Expand Down
24 changes: 22 additions & 2 deletions docs/docs/usage.rst
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,21 @@
Using Jedi
==========

|jedi| is can be used with a variety of plugins and software. It is also possible
to use |jedi| in the :ref:`Python shell or with IPython <repl-completion>`.
|jedi| is can be used with a variety of :ref:`plugins <editor-plugins>`,
`language servers <language-servers>` and other software.
It is also possible to use |jedi| in the :ref:`Python shell or with IPython
<repl-completion>`.

Below you can also find a list of :ref:`recipes for type hinting <recipes>`.

.. _language-servers:

Language Servers
--------------

- `jedi-language-server <https://github.com/pappasam/jedi-language-server>`_
- `python-language-server <https://github.com/palantir/python-language-server>`_
- `anakin-language-server <https://github.com/muffinmad/anakin-language-server>`_

.. _editor-plugins:

Expand Down Expand Up @@ -83,6 +93,16 @@ Web Debugger

- wdb_

xonsh shell
~~~~~~~~~~~

Jedi is a preinstalled extension in `xonsh shell <https://xon.sh/contents.html>`_.
Run the following command to enable:

::

xontrib load jedi

and many more!

.. _repl-completion:
Expand Down
10 changes: 8 additions & 2 deletions jedi/api/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@
sys.setrecursionlimit(3000)


class Script(object):
class Script:
"""
A Script is the base for completions, goto or whatever you want to do with
Jedi. The counter part of this class is :class:`Interpreter`, which works
Expand Down Expand Up @@ -122,7 +122,7 @@ def __init__(self, code=None, *, path=None, environment=None, project=None):
self._module_node, code = self._inference_state.parse_and_get_code(
code=code,
path=self.path,
use_latest_grammar=path and path.suffix == 'pyi',
use_latest_grammar=path and path.suffix == '.pyi',
cache=False, # No disk cache, because the current script often changes.
diff_cache=settings.fast_parser,
cache_path=settings.cache_directory,
Expand Down Expand Up @@ -157,6 +157,7 @@ def _get_module(self):
# We are in a stub file. Try to load the stub properly.
stub_module = load_proper_stub_module(
self._inference_state,
self._inference_state.latest_grammar,
file_io,
names,
self._module_node
Expand Down Expand Up @@ -234,6 +235,11 @@ def infer(self, line=None, column=None, *, only_stubs=False, prefer_stubs=False)
leaf = self._module_node.get_leaf_for_position(pos)
if leaf is None or leaf.type == 'string':
return []
if leaf.end_pos == (line, column) and leaf.type == 'operator':
next_ = leaf.get_next_leaf()
if next_.start_pos == leaf.end_pos \
and next_.type in ('number', 'string', 'keyword'):
leaf = next_

context = self._get_module_context().create_context(leaf)

Expand Down
36 changes: 26 additions & 10 deletions jedi/api/classes.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,18 +14,18 @@
the interesting information about all operations.
"""
import re
from pathlib import Path
from typing import Optional

from parso.python.tree import search_ancestor
from parso.tree import search_ancestor

from jedi import settings
from jedi import debug
from jedi.inference.utils import unite
from jedi.cache import memoize_method
from jedi.inference import imports
from jedi.inference.imports import ImportName
from jedi.inference.compiled.mixed import MixedName
from jedi.inference.gradual.typeshed import StubModuleValue
from jedi.inference.names import ImportName, SubModuleName
from jedi.inference.gradual.stub_value import StubModuleValue
from jedi.inference.gradual.conversion import convert_names, convert_values
from jedi.inference.base_value import ValueSet
from jedi.api.keywords import KeywordName
Expand Down Expand Up @@ -53,7 +53,7 @@ def _values_to_definitions(values):
return [Name(c.inference_state, c.name) for c in values]


class BaseName(object):
class BaseName:
"""
The base class for all definitions, completions and signatures.
"""
Expand Down Expand Up @@ -92,17 +92,15 @@ def _get_module_context(self):
return self._name.get_root_context()

@property
def module_path(self) -> Optional[str]:
def module_path(self) -> Optional[Path]:
"""
Shows the file path of a module. e.g. ``/usr/lib/python3.9/os.py``
:rtype: str or None
"""
module = self._get_module_context()
if module.is_stub() or not module.is_compiled():
# Compiled modules should not return a module path even if they
# have one.
path = self._get_module_context().py__file__()
path: Optional[Path] = self._get_module_context().py__file__()
if path is not None:
return path

Expand Down Expand Up @@ -185,7 +183,7 @@ def type(self):
tree_name.is_definition():
resolve = True

if isinstance(self._name, imports.SubModuleName) or resolve:
if isinstance(self._name, SubModuleName) or resolve:
for value in self._name.infer():
return value.api_type
return self._name.api_type
Expand Down Expand Up @@ -720,6 +718,24 @@ def type(self):

return super().type

def get_completion_prefix_length(self):
"""
Returns the length of the prefix being completed.
For example, completing ``isinstance``::
isinstan# <-- Cursor is here
would return 8, because len('isinstan') == 8.
Assuming the following function definition::
def foo(param=0):
pass
completing ``foo(par`` would return 3.
"""
return self._like_name_length

def __repr__(self):
return '<%s: %s>' % (type(self).__name__, self._name.get_public_name())

Expand Down
14 changes: 10 additions & 4 deletions jedi/api/completion_cache.py
Original file line number Diff line number Diff line change
@@ -1,16 +1,22 @@
_cache = {}
from typing import Dict, Tuple, Callable

CacheValues = Tuple[str, str, str]
CacheValuesCallback = Callable[[], CacheValues]

def save_entry(module_name, name, cache):

_cache: Dict[str, Dict[str, CacheValues]] = {}


def save_entry(module_name: str, name: str, cache: CacheValues) -> None:
try:
module_cache = _cache[module_name]
except KeyError:
module_cache = _cache[module_name] = {}
module_cache[name] = cache


def _create_get_from_cache(number):
def _get_from_cache(module_name, name, get_cache_values):
def _create_get_from_cache(number: int) -> Callable[[str, str, CacheValuesCallback], str]:
def _get_from_cache(module_name: str, name: str, get_cache_values: CacheValuesCallback) -> str:
try:
return _cache[module_name][name][number]
except KeyError:
Expand Down
7 changes: 4 additions & 3 deletions jedi/api/environment.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ class InvalidPythonEnvironment(Exception):
"""


class _BaseEnvironment(object):
class _BaseEnvironment:
@memoize_method
def get_grammar(self):
version_string = '%s.%s' % (self.version_info.major, self.version_info.minor)
Expand Down Expand Up @@ -121,7 +121,7 @@ def get_sys_path(self):
return self._get_subprocess().get_sys_path()


class _SameEnvironmentMixin(object):
class _SameEnvironmentMixin:
def __init__(self):
self._start_executable = self.executable = sys.executable
self.path = sys.prefix
Expand Down Expand Up @@ -384,7 +384,8 @@ def _get_executable_path(path, safe=True):


def _get_executables_from_windows_registry(version):
import winreg
# https://github.com/python/typeshed/pull/3794 adds winreg
import winreg # type: ignore[import]

# TODO: support Python Anaconda.
sub_keys = [
Expand Down
2 changes: 1 addition & 1 deletion jedi/api/errors.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ def parso_to_jedi_errors(grammar, module_node):
return [SyntaxError(e) for e in grammar.iter_errors(module_node)]


class SyntaxError(object):
class SyntaxError:
"""
Syntax errors are generated by :meth:`.Script.get_syntax_errors`.
"""
Expand Down
2 changes: 1 addition & 1 deletion jedi/api/helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -203,7 +203,7 @@ def filter_follow_imports(names, follow_builtin_imports=False):
yield name


class CallDetails(object):
class CallDetails:
def __init__(self, bracket_leaf, children, position):
['bracket_leaf', 'call_index', 'keyword_name_str']
self.bracket_leaf = bracket_leaf
Expand Down
2 changes: 1 addition & 1 deletion jedi/api/interpreter.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ def _create(inference_state, obj):
)


class NamespaceObject(object):
class NamespaceObject:
def __init__(self, dct):
self.__dict__ = dct

Expand Down
11 changes: 9 additions & 2 deletions jedi/api/keywords.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,16 @@
import pydoc
from contextlib import suppress
from typing import Dict, Optional

from jedi.inference.names import AbstractArbitraryName

from pydoc_data import topics as pydoc_topics
try:
# https://github.com/python/typeshed/pull/4351 adds pydoc_data
from pydoc_data import topics # type: ignore[import]
pydoc_topics: Optional[Dict[str, str]] = topics.topics
except ImportError:
# Python 3.6.8 embeddable does not have pydoc_data.
pydoc_topics = None


class KeywordName(AbstractArbitraryName):
Expand Down Expand Up @@ -40,6 +47,6 @@ def get_target(s):
return ''

try:
return pydoc_topics.topics[label].strip() if pydoc_topics else ''
return pydoc_topics[label].strip() if pydoc_topics else ''
except KeyError:
return ''
Loading

0 comments on commit f9cec89

Please sign in to comment.