forked from VimPlug/jedi
Implement all remaining Path issues and use it instead of strings
This commit is contained in:
@@ -20,7 +20,7 @@ def cast_path(string):
|
||||
"""
|
||||
if isinstance(string, bytes):
|
||||
return str(string, encoding='UTF-8', errors='replace')
|
||||
return string
|
||||
return str(string)
|
||||
|
||||
|
||||
def pickle_load(file):
|
||||
|
||||
@@ -142,7 +142,7 @@ class Script(object):
|
||||
|
||||
if project is None:
|
||||
# Load the Python grammar of the current interpreter.
|
||||
project = get_default_project(self.path)
|
||||
project = get_default_project(None if self.path is None else self.path.parent)
|
||||
# TODO deprecate and remove sys_path from the Script API.
|
||||
if sys_path is not None:
|
||||
project._sys_path = sys_path
|
||||
@@ -192,7 +192,7 @@ class Script(object):
|
||||
file_io = None
|
||||
else:
|
||||
file_io = KnownContentFileIO(cast_path(self.path), self._code)
|
||||
if self.path is not None and self.path.suffix == 'pyi':
|
||||
if self.path is not None and self.path.suffix == '.pyi':
|
||||
# We are in a stub file. Try to load the stub properly.
|
||||
stub_module = load_proper_stub_module(
|
||||
self._inference_state,
|
||||
|
||||
+5
-2
@@ -15,6 +15,7 @@ the interesting information about all operations.
|
||||
"""
|
||||
import re
|
||||
import warnings
|
||||
from typing import Optional
|
||||
|
||||
from parso.python.tree import search_ancestor
|
||||
|
||||
@@ -92,7 +93,7 @@ class BaseName(object):
|
||||
return self._name.get_root_context()
|
||||
|
||||
@property
|
||||
def module_path(self):
|
||||
def module_path(self) -> Optional[str]:
|
||||
"""
|
||||
Shows the file path of a module. e.g. ``/usr/lib/python3.9/os.py``
|
||||
|
||||
@@ -102,7 +103,9 @@ class BaseName(object):
|
||||
if module.is_stub() or not module.is_compiled():
|
||||
# Compiled modules should not return a module path even if they
|
||||
# have one.
|
||||
return self._get_module_context().py__file__()
|
||||
path = self._get_module_context().py__file__()
|
||||
if path is not None:
|
||||
return path
|
||||
|
||||
return None
|
||||
|
||||
|
||||
+1
-1
@@ -44,7 +44,7 @@ def match(string, like_name, fuzzy=False):
|
||||
|
||||
def sorted_definitions(defs):
|
||||
# Note: `or ''` below is required because `module_path` could be
|
||||
return sorted(defs, key=lambda x: (str(x.module_path) or '',
|
||||
return sorted(defs, key=lambda x: (str(x.module_path or ''),
|
||||
x.line or 0,
|
||||
x.column or 0,
|
||||
x.name))
|
||||
|
||||
+14
-5
@@ -80,6 +80,8 @@ class Project(object):
|
||||
|
||||
:param path: The path of the directory you want to use as a project.
|
||||
"""
|
||||
if isinstance(path, str):
|
||||
path = Path(path)
|
||||
with open(cls._get_json_path(path)) as f:
|
||||
version, data = json.load(f)
|
||||
|
||||
@@ -98,8 +100,9 @@ class Project(object):
|
||||
data.pop('_environment', None)
|
||||
data.pop('_django', None) # TODO make django setting public?
|
||||
data = {k.lstrip('_'): v for k, v in data.items()}
|
||||
data['path'] = str(data['path'])
|
||||
|
||||
self._path.mkdir(parents=True, exist_ok=True)
|
||||
self._get_config_folder_path(self._path).mkdir(parents=True, exist_ok=True)
|
||||
with open(self._get_json_path(self._path), 'w') as f:
|
||||
return json.dump((_SERIALIZER_VERSION, data), f)
|
||||
|
||||
@@ -129,11 +132,15 @@ class Project(object):
|
||||
self._path = path
|
||||
|
||||
self._environment_path = environment_path
|
||||
if sys_path is not None:
|
||||
# Remap potential pathlib.Path entries
|
||||
sys_path = list(map(str, sys_path))
|
||||
self._sys_path = sys_path
|
||||
self._smart_sys_path = smart_sys_path
|
||||
self._load_unsafe_extensions = load_unsafe_extensions
|
||||
self._django = False
|
||||
self.added_sys_path = list(added_sys_path)
|
||||
# Remap potential pathlib.Path entries
|
||||
self.added_sys_path = list(map(str, added_sys_path))
|
||||
"""The sys path that is going to be added at the end of the """
|
||||
|
||||
py2_comp(path, **kwargs)
|
||||
@@ -173,10 +180,10 @@ class Project(object):
|
||||
prefixed.append(str(self._path))
|
||||
|
||||
if inference_state.script_path is not None:
|
||||
suffixed += discover_buildout_paths(
|
||||
suffixed += map(str, discover_buildout_paths(
|
||||
inference_state,
|
||||
inference_state.script_path
|
||||
)
|
||||
))
|
||||
|
||||
if add_parent_paths:
|
||||
# Collect directories in upward search by:
|
||||
@@ -362,6 +369,8 @@ def get_default_project(path=None):
|
||||
"""
|
||||
if path is None:
|
||||
path = Path.cwd()
|
||||
elif isinstance(path, str):
|
||||
path = Path(path)
|
||||
|
||||
check = path.absolute()
|
||||
probable_path = None
|
||||
@@ -379,7 +388,7 @@ def get_default_project(path=None):
|
||||
# In the case that a __init__.py exists, it's in 99% just a
|
||||
# Python package and the project sits at least one level above.
|
||||
continue
|
||||
else:
|
||||
elif not dir.is_file():
|
||||
first_no_init_file = dir
|
||||
|
||||
if _is_django_path(dir):
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
import difflib
|
||||
from pathlib import Path
|
||||
from typing import Dict
|
||||
|
||||
from parso import split_lines
|
||||
|
||||
@@ -47,8 +49,8 @@ class ChangedFile(object):
|
||||
to_p = self._to_path.relative_to(project_path)
|
||||
diff = difflib.unified_diff(
|
||||
old_lines, new_lines,
|
||||
fromfile=from_p,
|
||||
tofile=to_p,
|
||||
fromfile=str(from_p),
|
||||
tofile=str(to_p),
|
||||
)
|
||||
# Apparently there's a space at the end of the diff - for whatever
|
||||
# reason.
|
||||
@@ -76,17 +78,15 @@ class Refactoring(object):
|
||||
self._renames = renames
|
||||
self._file_to_node_changes = file_to_node_changes
|
||||
|
||||
def get_changed_files(self):
|
||||
"""
|
||||
Returns a path to ``ChangedFile`` map.
|
||||
"""
|
||||
def get_changed_files(self) -> Dict[Path, ChangedFile]:
|
||||
def calculate_to_path(p):
|
||||
if p is None:
|
||||
return p
|
||||
p = str(p)
|
||||
for from_, to in renames:
|
||||
if p.startswith(from_):
|
||||
p = to + p[len(from_):]
|
||||
return p
|
||||
if p.startswith(str(from_)):
|
||||
p = str(to) + p[len(str(from_)):]
|
||||
return Path(p)
|
||||
|
||||
renames = self.get_renames()
|
||||
return {
|
||||
@@ -144,7 +144,8 @@ def rename(inference_state, definitions, new_name):
|
||||
for d in definitions:
|
||||
tree_name = d._name.tree_name
|
||||
if d.type == 'module' and tree_name is None:
|
||||
file_renames.add(_calculate_rename(d.module_path, new_name))
|
||||
p = None if d.module_path is None else Path(d.module_path)
|
||||
file_renames.add(_calculate_rename(p, new_name))
|
||||
else:
|
||||
# This private access is ok in a way. It's not public to
|
||||
# protect Jedi users from seeing it.
|
||||
|
||||
@@ -4,6 +4,7 @@ Imitate the parser representation.
|
||||
import re
|
||||
from functools import partial
|
||||
from inspect import Parameter
|
||||
from pathlib import Path
|
||||
|
||||
from jedi import debug
|
||||
from jedi.inference.utils import to_list
|
||||
@@ -312,7 +313,10 @@ class CompiledModule(CompiledValue):
|
||||
return tuple(name.split('.'))
|
||||
|
||||
def py__file__(self):
|
||||
return cast_path(self.access_handle.py__file__())
|
||||
path = cast_path(self.access_handle.py__file__())
|
||||
if path is None:
|
||||
return None
|
||||
return Path(path)
|
||||
|
||||
|
||||
class CompiledName(AbstractNameDefinition):
|
||||
|
||||
@@ -2,6 +2,7 @@ import os
|
||||
import re
|
||||
from functools import wraps
|
||||
from collections import namedtuple
|
||||
from pathlib import Path
|
||||
|
||||
from jedi import settings
|
||||
from jedi.file_io import FileIO
|
||||
@@ -11,10 +12,10 @@ from jedi.inference.base_value import ValueSet, NO_VALUES
|
||||
from jedi.inference.gradual.stub_value import TypingModuleWrapper, StubModuleValue
|
||||
from jedi.inference.value import ModuleValue
|
||||
|
||||
_jedi_path = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
|
||||
TYPESHED_PATH = os.path.join(_jedi_path, 'third_party', 'typeshed')
|
||||
DJANGO_INIT_PATH = os.path.join(_jedi_path, 'third_party', 'django-stubs',
|
||||
'django-stubs', '__init__.pyi')
|
||||
_jedi_path = Path(__file__).parent.parent.parent
|
||||
TYPESHED_PATH = _jedi_path.joinpath('third_party', 'typeshed')
|
||||
DJANGO_INIT_PATH = _jedi_path.joinpath('third_party', 'django-stubs',
|
||||
'django-stubs', '__init__.pyi')
|
||||
|
||||
_IMPORT_MAP = dict(
|
||||
_collections='collections',
|
||||
@@ -60,7 +61,7 @@ def _create_stub_map(directory_path_info):
|
||||
def _get_typeshed_directories(version_info):
|
||||
check_version_list = ['2and3', '3']
|
||||
for base in ['stdlib', 'third_party']:
|
||||
base_path = os.path.join(TYPESHED_PATH, base)
|
||||
base_path = TYPESHED_PATH.joinpath(base)
|
||||
base_list = os.listdir(base_path)
|
||||
for base_list_entry in base_list:
|
||||
match = re.match(r'(\d+)\.(\d+)$', base_list_entry)
|
||||
@@ -70,7 +71,7 @@ def _get_typeshed_directories(version_info):
|
||||
|
||||
for check_version in check_version_list:
|
||||
is_third_party = base != 'stdlib'
|
||||
yield PathInfo(os.path.join(base_path, check_version), is_third_party)
|
||||
yield PathInfo(str(base_path.joinpath(check_version)), is_third_party)
|
||||
|
||||
|
||||
_version_cache = {}
|
||||
@@ -181,7 +182,7 @@ def _try_to_load_stub(inference_state, import_names, python_value_set,
|
||||
return _try_to_load_stub_from_file(
|
||||
inference_state,
|
||||
python_value_set,
|
||||
file_io=FileIO(DJANGO_INIT_PATH),
|
||||
file_io=FileIO(str(DJANGO_INIT_PATH)),
|
||||
import_names=import_names,
|
||||
)
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import os
|
||||
from pathlib import Path
|
||||
|
||||
from jedi.inference.gradual.typeshed import TYPESHED_PATH, create_stub_module
|
||||
|
||||
@@ -9,14 +10,18 @@ def load_proper_stub_module(inference_state, file_io, import_names, module_node)
|
||||
module.
|
||||
"""
|
||||
path = file_io.path
|
||||
assert path.endswith('.pyi')
|
||||
if path.startswith(TYPESHED_PATH):
|
||||
# /foo/stdlib/3/os/__init__.pyi -> stdlib/3/os/__init__
|
||||
rest = path[len(TYPESHED_PATH) + 1: -4]
|
||||
split_paths = tuple(rest.split(os.path.sep))
|
||||
path = Path(path)
|
||||
assert path.suffix == '.pyi'
|
||||
try:
|
||||
relative_path = path.relative_to(TYPESHED_PATH)
|
||||
except ValueError:
|
||||
pass
|
||||
else:
|
||||
# /[...]/stdlib/3/os/__init__.pyi -> stdlib/3/os/__init__
|
||||
rest = relative_path.with_suffix('')
|
||||
# Remove the stdlib/3 or third_party/3.6 part
|
||||
import_names = split_paths[2:]
|
||||
if import_names[-1] == '__init__':
|
||||
import_names = rest.parts[2:]
|
||||
if rest.name == '__init__':
|
||||
import_names = import_names[:-1]
|
||||
|
||||
if import_names is not None:
|
||||
|
||||
@@ -148,7 +148,7 @@ def discover_buildout_paths(inference_state, script_path):
|
||||
|
||||
|
||||
def _get_paths_from_buildout_script(inference_state, buildout_script_path):
|
||||
file_io = FileIO(buildout_script_path)
|
||||
file_io = FileIO(str(buildout_script_path))
|
||||
try:
|
||||
module_node = inference_state.parse(
|
||||
file_io=file_io,
|
||||
@@ -164,7 +164,7 @@ def _get_paths_from_buildout_script(inference_state, buildout_script_path):
|
||||
inference_state, module_node,
|
||||
file_io=file_io,
|
||||
string_names=None,
|
||||
code_lines=get_cached_code_lines(inference_state.grammar, buildout_script_path),
|
||||
code_lines=get_cached_code_lines(inference_state.grammar, str(buildout_script_path)),
|
||||
).as_context()
|
||||
for path in check_sys_path_modifications(module_context):
|
||||
yield path
|
||||
@@ -228,6 +228,8 @@ def transform_path_to_dotted(sys_path, module_path):
|
||||
"""
|
||||
# First remove the suffix.
|
||||
module_path = remove_python_path_suffix(module_path)
|
||||
if module_path.name.startswith('.'):
|
||||
return None, False
|
||||
|
||||
# Once the suffix was removed we are using the files as we know them. This
|
||||
# means that if someone uses an ending like .vim for a Python file, .vim
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
from pathlib import Path
|
||||
|
||||
from parso.python.tree import search_ancestor
|
||||
from jedi.inference.cache import inference_state_method_cache
|
||||
from jedi.inference.imports import load_module_from_path
|
||||
@@ -128,7 +130,7 @@ def _iter_pytest_modules(module_context, skip_own_module=False):
|
||||
sys_path = module_context.inference_state.get_sys_path()
|
||||
while any(folder.path.startswith(p) for p in sys_path):
|
||||
file_io = folder.get_file_io('conftest.py')
|
||||
if file_io.path != module_context.py__file__():
|
||||
if Path(file_io.path) != module_context.py__file__():
|
||||
try:
|
||||
m = load_module_from_path(module_context.inference_state, file_io)
|
||||
yield m.as_context()
|
||||
|
||||
Reference in New Issue
Block a user