1
0
forked from VimPlug/jedi

Implement all remaining Path issues and use it instead of strings

This commit is contained in:
Dave Halter
2020-07-12 01:14:00 +02:00
parent db0e90763b
commit 480a464179
23 changed files with 131 additions and 97 deletions

View File

@@ -20,7 +20,7 @@ def cast_path(string):
""" """
if isinstance(string, bytes): if isinstance(string, bytes):
return str(string, encoding='UTF-8', errors='replace') return str(string, encoding='UTF-8', errors='replace')
return string return str(string)
def pickle_load(file): def pickle_load(file):

View File

@@ -142,7 +142,7 @@ class Script(object):
if project is None: if project is None:
# Load the Python grammar of the current interpreter. # 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. # TODO deprecate and remove sys_path from the Script API.
if sys_path is not None: if sys_path is not None:
project._sys_path = sys_path project._sys_path = sys_path
@@ -192,7 +192,7 @@ class Script(object):
file_io = None file_io = None
else: else:
file_io = KnownContentFileIO(cast_path(self.path), self._code) 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. # We are in a stub file. Try to load the stub properly.
stub_module = load_proper_stub_module( stub_module = load_proper_stub_module(
self._inference_state, self._inference_state,

View File

@@ -15,6 +15,7 @@ the interesting information about all operations.
""" """
import re import re
import warnings import warnings
from typing import Optional
from parso.python.tree import search_ancestor from parso.python.tree import search_ancestor
@@ -92,7 +93,7 @@ class BaseName(object):
return self._name.get_root_context() return self._name.get_root_context()
@property @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`` 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(): if module.is_stub() or not module.is_compiled():
# Compiled modules should not return a module path even if they # Compiled modules should not return a module path even if they
# have one. # 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 return None

View File

@@ -44,7 +44,7 @@ def match(string, like_name, fuzzy=False):
def sorted_definitions(defs): def sorted_definitions(defs):
# Note: `or ''` below is required because `module_path` could be # 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.line or 0,
x.column or 0, x.column or 0,
x.name)) x.name))

View File

@@ -80,6 +80,8 @@ class Project(object):
:param path: The path of the directory you want to use as a project. :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: with open(cls._get_json_path(path)) as f:
version, data = json.load(f) version, data = json.load(f)
@@ -98,8 +100,9 @@ class Project(object):
data.pop('_environment', None) data.pop('_environment', None)
data.pop('_django', None) # TODO make django setting public? data.pop('_django', None) # TODO make django setting public?
data = {k.lstrip('_'): v for k, v in data.items()} 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: with open(self._get_json_path(self._path), 'w') as f:
return json.dump((_SERIALIZER_VERSION, data), f) return json.dump((_SERIALIZER_VERSION, data), f)
@@ -129,11 +132,15 @@ class Project(object):
self._path = path self._path = path
self._environment_path = environment_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._sys_path = sys_path
self._smart_sys_path = smart_sys_path self._smart_sys_path = smart_sys_path
self._load_unsafe_extensions = load_unsafe_extensions self._load_unsafe_extensions = load_unsafe_extensions
self._django = False 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 """ """The sys path that is going to be added at the end of the """
py2_comp(path, **kwargs) py2_comp(path, **kwargs)
@@ -173,10 +180,10 @@ class Project(object):
prefixed.append(str(self._path)) prefixed.append(str(self._path))
if inference_state.script_path is not None: if inference_state.script_path is not None:
suffixed += discover_buildout_paths( suffixed += map(str, discover_buildout_paths(
inference_state, inference_state,
inference_state.script_path inference_state.script_path
) ))
if add_parent_paths: if add_parent_paths:
# Collect directories in upward search by: # Collect directories in upward search by:
@@ -362,6 +369,8 @@ def get_default_project(path=None):
""" """
if path is None: if path is None:
path = Path.cwd() path = Path.cwd()
elif isinstance(path, str):
path = Path(path)
check = path.absolute() check = path.absolute()
probable_path = None 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 # 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. # Python package and the project sits at least one level above.
continue continue
else: elif not dir.is_file():
first_no_init_file = dir first_no_init_file = dir
if _is_django_path(dir): if _is_django_path(dir):

View File

@@ -1,4 +1,6 @@
import difflib import difflib
from pathlib import Path
from typing import Dict
from parso import split_lines from parso import split_lines
@@ -47,8 +49,8 @@ class ChangedFile(object):
to_p = self._to_path.relative_to(project_path) to_p = self._to_path.relative_to(project_path)
diff = difflib.unified_diff( diff = difflib.unified_diff(
old_lines, new_lines, old_lines, new_lines,
fromfile=from_p, fromfile=str(from_p),
tofile=to_p, tofile=str(to_p),
) )
# Apparently there's a space at the end of the diff - for whatever # Apparently there's a space at the end of the diff - for whatever
# reason. # reason.
@@ -76,17 +78,15 @@ class Refactoring(object):
self._renames = renames self._renames = renames
self._file_to_node_changes = file_to_node_changes self._file_to_node_changes = file_to_node_changes
def get_changed_files(self): def get_changed_files(self) -> Dict[Path, ChangedFile]:
"""
Returns a path to ``ChangedFile`` map.
"""
def calculate_to_path(p): def calculate_to_path(p):
if p is None: if p is None:
return p return p
p = str(p)
for from_, to in renames: for from_, to in renames:
if p.startswith(from_): if p.startswith(str(from_)):
p = to + p[len(from_):] p = str(to) + p[len(str(from_)):]
return p return Path(p)
renames = self.get_renames() renames = self.get_renames()
return { return {
@@ -144,7 +144,8 @@ def rename(inference_state, definitions, new_name):
for d in definitions: for d in definitions:
tree_name = d._name.tree_name tree_name = d._name.tree_name
if d.type == 'module' and tree_name is None: 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: else:
# This private access is ok in a way. It's not public to # This private access is ok in a way. It's not public to
# protect Jedi users from seeing it. # protect Jedi users from seeing it.

View File

@@ -4,6 +4,7 @@ Imitate the parser representation.
import re import re
from functools import partial from functools import partial
from inspect import Parameter from inspect import Parameter
from pathlib import Path
from jedi import debug from jedi import debug
from jedi.inference.utils import to_list from jedi.inference.utils import to_list
@@ -312,7 +313,10 @@ class CompiledModule(CompiledValue):
return tuple(name.split('.')) return tuple(name.split('.'))
def py__file__(self): 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): class CompiledName(AbstractNameDefinition):

View File

@@ -2,6 +2,7 @@ import os
import re import re
from functools import wraps from functools import wraps
from collections import namedtuple from collections import namedtuple
from pathlib import Path
from jedi import settings from jedi import settings
from jedi.file_io import FileIO 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.gradual.stub_value import TypingModuleWrapper, StubModuleValue
from jedi.inference.value import ModuleValue from jedi.inference.value import ModuleValue
_jedi_path = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) _jedi_path = Path(__file__).parent.parent.parent
TYPESHED_PATH = os.path.join(_jedi_path, 'third_party', 'typeshed') TYPESHED_PATH = _jedi_path.joinpath('third_party', 'typeshed')
DJANGO_INIT_PATH = os.path.join(_jedi_path, 'third_party', 'django-stubs', DJANGO_INIT_PATH = _jedi_path.joinpath('third_party', 'django-stubs',
'django-stubs', '__init__.pyi') 'django-stubs', '__init__.pyi')
_IMPORT_MAP = dict( _IMPORT_MAP = dict(
_collections='collections', _collections='collections',
@@ -60,7 +61,7 @@ def _create_stub_map(directory_path_info):
def _get_typeshed_directories(version_info): def _get_typeshed_directories(version_info):
check_version_list = ['2and3', '3'] check_version_list = ['2and3', '3']
for base in ['stdlib', 'third_party']: 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) base_list = os.listdir(base_path)
for base_list_entry in base_list: for base_list_entry in base_list:
match = re.match(r'(\d+)\.(\d+)$', base_list_entry) 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: for check_version in check_version_list:
is_third_party = base != 'stdlib' 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 = {} _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( return _try_to_load_stub_from_file(
inference_state, inference_state,
python_value_set, python_value_set,
file_io=FileIO(DJANGO_INIT_PATH), file_io=FileIO(str(DJANGO_INIT_PATH)),
import_names=import_names, import_names=import_names,
) )

View File

@@ -1,4 +1,5 @@
import os import os
from pathlib import Path
from jedi.inference.gradual.typeshed import TYPESHED_PATH, create_stub_module 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. module.
""" """
path = file_io.path path = file_io.path
assert path.endswith('.pyi') path = Path(path)
if path.startswith(TYPESHED_PATH): assert path.suffix == '.pyi'
# /foo/stdlib/3/os/__init__.pyi -> stdlib/3/os/__init__ try:
rest = path[len(TYPESHED_PATH) + 1: -4] relative_path = path.relative_to(TYPESHED_PATH)
split_paths = tuple(rest.split(os.path.sep)) 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 # Remove the stdlib/3 or third_party/3.6 part
import_names = split_paths[2:] import_names = rest.parts[2:]
if import_names[-1] == '__init__': if rest.name == '__init__':
import_names = import_names[:-1] import_names = import_names[:-1]
if import_names is not None: if import_names is not None:

View File

@@ -148,7 +148,7 @@ def discover_buildout_paths(inference_state, script_path):
def _get_paths_from_buildout_script(inference_state, buildout_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: try:
module_node = inference_state.parse( module_node = inference_state.parse(
file_io=file_io, file_io=file_io,
@@ -164,7 +164,7 @@ def _get_paths_from_buildout_script(inference_state, buildout_script_path):
inference_state, module_node, inference_state, module_node,
file_io=file_io, file_io=file_io,
string_names=None, 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() ).as_context()
for path in check_sys_path_modifications(module_context): for path in check_sys_path_modifications(module_context):
yield path yield path
@@ -228,6 +228,8 @@ def transform_path_to_dotted(sys_path, module_path):
""" """
# First remove the suffix. # First remove the suffix.
module_path = remove_python_path_suffix(module_path) 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 # 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 # means that if someone uses an ending like .vim for a Python file, .vim

View File

@@ -1,3 +1,5 @@
from pathlib import Path
from parso.python.tree import search_ancestor from parso.python.tree import search_ancestor
from jedi.inference.cache import inference_state_method_cache from jedi.inference.cache import inference_state_method_cache
from jedi.inference.imports import load_module_from_path 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() sys_path = module_context.inference_state.get_sys_path()
while any(folder.path.startswith(p) for p in sys_path): while any(folder.path.startswith(p) for p in sys_path):
file_io = folder.get_file_io('conftest.py') 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: try:
m = load_module_from_path(module_context.inference_state, file_io) m = load_module_from_path(module_context.inference_state, file_io)
yield m.as_context() yield m.as_context()

View File

@@ -7,14 +7,14 @@ from contextlib import contextmanager
import os import os
import pytest import pytest
from os.path import abspath, dirname, join
from functools import partial, wraps from functools import partial, wraps
from jedi import Project from jedi import Project
from pathlib import Path
test_dir = dirname(abspath(__file__)) test_dir = Path(__file__).absolute().parent
test_dir_project = Project(test_dir) test_dir_project = Project(test_dir)
root_dir = dirname(test_dir) root_dir = test_dir.parent
example_dir = join(test_dir, 'examples') example_dir = test_dir.joinpath('examples')
sample_int = 1 # This is used in completion/imports.py sample_int = 1 # This is used in completion/imports.py
@@ -25,7 +25,7 @@ skip_if_not_windows = partial(pytest.param,
def get_example_dir(*names): def get_example_dir(*names):
return join(example_dir, *names) return example_dir.joinpath(*names)
def cwd_at(path): def cwd_at(path):
@@ -46,10 +46,10 @@ def cwd_at(path):
@contextmanager @contextmanager
def set_cwd(path, absolute_path=False): def set_cwd(path, absolute_path=False):
repo_root = os.path.dirname(test_dir) repo_root = test_dir.parent
oldcwd = os.getcwd() oldcwd = Path.cwd()
os.chdir(os.path.join(repo_root, path)) os.chdir(repo_root.joinpath(path))
try: try:
yield yield
finally: finally:

View File

@@ -22,7 +22,7 @@ def test_preload_modules():
# Filter the typeshed parser cache. # Filter the typeshed parser cache.
typeshed_cache_count = sum( typeshed_cache_count = sum(
1 for path in grammar_cache 1 for path in grammar_cache
if path is not None and path.startswith(typeshed.TYPESHED_PATH) if path is not None and str(path).startswith(str(typeshed.TYPESHED_PATH))
) )
# +1 for None module (currently used) # +1 for None module (currently used)
assert len(grammar_cache) - typeshed_cache_count == len(modules) + 1 assert len(grammar_cache) - typeshed_cache_count == len(modules) + 1
@@ -210,11 +210,11 @@ def test_goto_follow_imports(Script):
import inspect import inspect
inspect.isfunction""") inspect.isfunction""")
definition, = Script(code).goto(column=0, follow_imports=True) definition, = Script(code).goto(column=0, follow_imports=True)
assert 'inspect.py' in definition.module_path assert definition.module_path.name == 'inspect.py'
assert (definition.line, definition.column) == (1, 0) assert (definition.line, definition.column) == (1, 0)
definition, = Script(code).goto(follow_imports=True) definition, = Script(code).goto(follow_imports=True)
assert 'inspect.py' in definition.module_path assert definition.module_path.name == 'inspect.py'
assert (definition.line, definition.column) > (1, 0) assert (definition.line, definition.column) > (1, 0)
code = '''def param(p): pass\nparam(1)''' code = '''def param(p): pass\nparam(1)'''
@@ -245,11 +245,11 @@ def test_goto_module(Script):
assert module.module_path == expected assert module.module_path == expected
base_path = get_example_dir('simple_import') base_path = get_example_dir('simple_import')
path = os.path.join(base_path, '__init__.py') path = base_path.joinpath('__init__.py')
check(1, os.path.join(base_path, 'module.py')) check(1, base_path.joinpath('module.py'))
check(1, os.path.join(base_path, 'module.py'), follow_imports=True) check(1, base_path.joinpath('module.py'), follow_imports=True)
check(5, os.path.join(base_path, 'module2.py')) check(5, base_path.joinpath('module2.py'))
def test_goto_definition_cursor(Script): def test_goto_definition_cursor(Script):

View File

@@ -3,7 +3,6 @@
from textwrap import dedent from textwrap import dedent
from inspect import cleandoc from inspect import cleandoc
import os
import pytest import pytest
@@ -534,8 +533,8 @@ def test_execute(Script, code, description):
('from pkg import Foo; Foo().bar', 'bar', 'module.py'), ('from pkg import Foo; Foo().bar', 'bar', 'module.py'),
]) ])
def test_inheritance_module_path(Script, goto, code, name, file_name): def test_inheritance_module_path(Script, goto, code, name, file_name):
base_path = os.path.join(get_example_dir('inheritance'), 'pkg') base_path = get_example_dir('inheritance', 'pkg')
whatever_path = os.path.join(base_path, 'NOT_EXISTING.py') whatever_path = base_path.joinpath('NOT_EXISTING.py')
script = Script(code, path=whatever_path) script = Script(code, path=whatever_path)
if goto is None: if goto is None:
@@ -544,7 +543,7 @@ def test_inheritance_module_path(Script, goto, code, name, file_name):
func, = script.goto(follow_imports=goto) func, = script.goto(follow_imports=goto)
assert func.type == 'function' assert func.type == 'function'
assert func.name == name assert func.name == name
assert func.module_path == os.path.join(base_path, file_name) assert func.module_path == base_path.joinpath(file_name)
def test_definition_goto_follow_imports(Script): def test_definition_goto_follow_imports(Script):

View File

@@ -221,8 +221,8 @@ current_dirname = os.path.basename(dirname(dirname(dirname(__file__))))
('example.py', 'rb"' + join('..', current_dirname, 'tes'), None, ['t' + s]), ('example.py', 'rb"' + join('..', current_dirname, 'tes'), None, ['t' + s]),
# Absolute paths # Absolute paths
(None, '"' + join(root_dir, 'test', 'test_ca'), None, ['che.py"']), (None, f'"{root_dir.joinpath("test", "test_ca")}', None, ['che.py"']),
(None, '"%s"' % join(root_dir, 'test', 'test_ca'), len(root_dir) + 14, ['che.py']), (None, f'"{root_dir.joinpath("test", "test_ca")}"', len(str(root_dir)) + 14, ['che.py']),
# Longer quotes # Longer quotes
('example.py', 'r"""test', None, [s]), ('example.py', 'r"""test', None, [s]),

View File

@@ -41,7 +41,7 @@ def test_keyword_attributes(Script):
assert def_.line is def_.column is None assert def_.line is def_.column is None
assert def_.in_builtin_module() is True assert def_.in_builtin_module() is True
assert def_.module_name == 'builtins' assert def_.module_name == 'builtins'
assert 'typeshed' in def_.module_path assert 'typeshed' in def_.module_path.parts
assert def_.type == 'keyword' assert def_.type == 'keyword'

View File

@@ -1,4 +1,5 @@
import os import os
from pathlib import Path
import pytest import pytest
@@ -21,13 +22,12 @@ def test_django_default_project(Script):
def test_django_default_project_of_file(Script): def test_django_default_project_of_file(Script):
project = get_default_project(__file__) project = get_default_project(__file__)
d = os.path.dirname assert project._path == Path(__file__).parent.parent.parent
assert project._path == d(d(d(__file__)))
def test_interpreter_project_path(): def test_interpreter_project_path():
# Run from anywhere it should be the cwd. # Run from anywhere it should be the cwd.
dir = os.path.join(root_dir, 'test') dir = Path(root_dir).joinpath('test')
with set_cwd(dir): with set_cwd(dir):
project = Interpreter('', [locals()])._inference_state.project project = Interpreter('', [locals()])._inference_state.project
assert project._path == dir assert project._path == dir

View File

@@ -1,5 +1,6 @@
import os import os
from textwrap import dedent from textwrap import dedent
from pathlib import Path
import pytest import pytest
@@ -10,22 +11,22 @@ import jedi
def dir_with_content(tmpdir): def dir_with_content(tmpdir):
with open(os.path.join(tmpdir.strpath, 'modx.py'), 'w', newline='') as f: with open(os.path.join(tmpdir.strpath, 'modx.py'), 'w', newline='') as f:
f.write('import modx\nfoo\n') # self reference f.write('import modx\nfoo\n') # self reference
return tmpdir.strpath return Path(tmpdir.strpath)
def test_rename_mod(Script, dir_with_content): def test_rename_mod(Script, dir_with_content):
script = Script( script = Script(
'import modx; modx\n', 'import modx; modx\n',
path=os.path.join(dir_with_content, 'some_script.py'), path=dir_with_content.joinpath('some_script.py'),
project=jedi.Project(dir_with_content), project=jedi.Project(dir_with_content),
) )
refactoring = script.rename(line=1, new_name='modr') refactoring = script.rename(line=1, new_name='modr')
refactoring.apply() refactoring.apply()
p1 = os.path.join(dir_with_content, 'modx.py') p1 = dir_with_content.joinpath('modx.py')
p2 = os.path.join(dir_with_content, 'modr.py') p2 = dir_with_content.joinpath('modr.py')
expected_code = 'import modr\nfoo\n' expected_code = 'import modr\nfoo\n'
assert not os.path.exists(p1) assert not p1.exists()
with open(p2, newline='') as f: with open(p2, newline='') as f:
assert f.read() == expected_code assert f.read() == expected_code

View File

@@ -1,5 +1,6 @@
import os import os
from textwrap import dedent from textwrap import dedent
from pathlib import Path
from jedi.inference.sys_path import _get_parent_dir_with_file, \ from jedi.inference.sys_path import _get_parent_dir_with_file, \
_get_buildout_script_paths, check_sys_path_modifications _get_buildout_script_paths, check_sys_path_modifications
@@ -13,18 +14,18 @@ def check_module_test(Script, code):
def test_parent_dir_with_file(Script): def test_parent_dir_with_file(Script):
path = get_example_dir('buildout_project', 'src', 'proj_name') path = Path(get_example_dir('buildout_project', 'src', 'proj_name'))
parent = _get_parent_dir_with_file(path, 'buildout.cfg') parent = _get_parent_dir_with_file(path, 'buildout.cfg')
assert parent is not None assert parent is not None
assert parent.endswith(os.path.join('test', 'examples', 'buildout_project')) assert str(parent).endswith(os.path.join('test', 'examples', 'buildout_project'))
def test_buildout_detection(Script): def test_buildout_detection(Script):
path = get_example_dir('buildout_project', 'src', 'proj_name') path = Path(get_example_dir('buildout_project', 'src', 'proj_name'))
scripts = list(_get_buildout_script_paths(os.path.join(path, 'module_name.py'))) paths = list(_get_buildout_script_paths(path.joinpath('module_name.py')))
assert len(scripts) == 1 assert len(paths) == 1
appdir_path = os.path.normpath(os.path.join(path, '../../bin/app')) appdir_path = os.path.normpath(os.path.join(path, '../../bin/app'))
assert scripts[0] == appdir_path assert str(paths[0]) == appdir_path
def test_append_on_non_sys_path(Script): def test_append_on_non_sys_path(Script):
@@ -79,4 +80,4 @@ def test_path_from_sys_path_assignment(Script):
paths = check_module_test(Script, code) paths = check_module_test(Script, code)
assert 1 not in paths assert 1 not in paths
assert '/home/test/.buildout/eggs/important_package.egg' in paths assert '/home/test/.buildout/eggs/important_package.egg' in map(str, paths)

View File

@@ -87,4 +87,4 @@ def test_infer_and_goto(Script, code, full_name, has_stub, has_python, way,
assert has_python == (not d.is_stub()) assert has_python == (not d.is_stub())
assert d.full_name == full_name assert d.full_name == full_name
assert d.is_stub() == d.module_path.endswith('.pyi') assert d.is_stub() == (d.module_path.suffix == '.pyi')

View File

@@ -14,7 +14,7 @@ TYPESHED_PYTHON3 = os.path.join(typeshed.TYPESHED_PATH, 'stdlib', '3')
def test_get_typeshed_directories(): def test_get_typeshed_directories():
def get_dirs(version_info): def get_dirs(version_info):
return { return {
p.path.replace(typeshed.TYPESHED_PATH, '').lstrip(os.path.sep) p.path.replace(str(typeshed.TYPESHED_PATH), '').lstrip(os.path.sep)
for p in typeshed._get_typeshed_directories(version_info) for p in typeshed._get_typeshed_directories(version_info)
} }
@@ -52,7 +52,7 @@ def test_keywords_variable(Script):
assert seq.name == 'Sequence' assert seq.name == 'Sequence'
# This points towards the typeshed implementation # This points towards the typeshed implementation
stub_seq, = seq.goto(only_stubs=True) stub_seq, = seq.goto(only_stubs=True)
assert typeshed.TYPESHED_PATH in stub_seq.module_path assert str(stub_seq.module_path).startswith(str(typeshed.TYPESHED_PATH))
def test_class(Script): def test_class(Script):
@@ -91,8 +91,12 @@ def test_sys_exc_info(Script):
none, def_ = Script(code + '[1]').infer() none, def_ = Script(code + '[1]').infer()
# It's an optional. # It's an optional.
assert def_.name == 'BaseException' assert def_.name == 'BaseException'
assert def_.module_path == typeshed.TYPESHED_PATH.joinpath(
'stdlib', '2and3', 'builtins.pyi'
)
assert def_.type == 'instance' assert def_.type == 'instance'
assert none.name == 'NoneType' assert none.name == 'NoneType'
assert none.module_path is None
none, def_ = Script(code + '[0]').infer() none, def_ = Script(code + '[0]').infer()
assert def_.name == 'BaseException' assert def_.name == 'BaseException'
@@ -111,7 +115,7 @@ def test_sys_hexversion(Script):
script = Script('import sys; sys.hexversion') script = Script('import sys; sys.hexversion')
def_, = script.complete() def_, = script.complete()
assert isinstance(def_._name, StubName), def_._name assert isinstance(def_._name, StubName), def_._name
assert typeshed.TYPESHED_PATH in def_.module_path assert str(def_.module_path).startswith(str(typeshed.TYPESHED_PATH))
def_, = script.infer() def_, = script.infer()
assert def_.name == 'int' assert def_.name == 'int'
@@ -138,14 +142,14 @@ def test_type_var(Script):
def test_math_is_stub(Script, code, full_name): def test_math_is_stub(Script, code, full_name):
s = Script(code) s = Script(code)
cos, = s.infer() cos, = s.infer()
wanted = os.path.join('typeshed', 'stdlib', '2and3', 'math.pyi') wanted = ('typeshed', 'stdlib', '2and3', 'math.pyi')
assert cos.module_path.endswith(wanted) assert cos.module_path.parts[-4:] == wanted
assert cos.is_stub() is True assert cos.is_stub() is True
assert cos.goto(only_stubs=True) == [cos] assert cos.goto(only_stubs=True) == [cos]
assert cos.full_name == full_name assert cos.full_name == full_name
cos, = s.goto() cos, = s.goto()
assert cos.module_path.endswith(wanted) assert cos.module_path.parts[-4:] == wanted
assert cos.goto(only_stubs=True) == [cos] assert cos.goto(only_stubs=True) == [cos]
assert cos.is_stub() is True assert cos.is_stub() is True
assert cos.full_name == full_name assert cos.full_name == full_name

View File

@@ -4,6 +4,7 @@ Tests".
""" """
import os import os
from pathlib import Path
import pytest import pytest
@@ -38,11 +39,11 @@ def test_find_module_not_package():
assert is_package is False assert is_package is False
pkg_zip_path = get_example_dir('zipped_imports', 'pkg.zip') pkg_zip_path = Path(get_example_dir('zipped_imports', 'pkg.zip'))
def test_find_module_package_zipped(Script, inference_state, environment): def test_find_module_package_zipped(Script, inference_state, environment):
sys_path = environment.get_sys_path() + [pkg_zip_path] sys_path = environment.get_sys_path() + [str(pkg_zip_path)]
project = Project('.', sys_path=sys_path) project = Project('.', sys_path=sys_path)
script = Script('import pkg; pkg.mod', project=project) script = Script('import pkg; pkg.mod', project=project)
@@ -86,14 +87,14 @@ def test_find_module_package_zipped(Script, inference_state, environment):
) )
def test_correct_zip_package_behavior(Script, inference_state, environment, code, def test_correct_zip_package_behavior(Script, inference_state, environment, code,
file, package, path): file, package, path):
sys_path = environment.get_sys_path() + [pkg_zip_path] sys_path = environment.get_sys_path() + [str(pkg_zip_path)]
pkg, = Script(code, project=Project('.', sys_path=sys_path)).infer() pkg, = Script(code, project=Project('.', sys_path=sys_path)).infer()
value, = pkg._name.infer() value, = pkg._name.infer()
assert value.py__file__() == os.path.join(pkg_zip_path, 'pkg', file) assert value.py__file__() == pkg_zip_path.joinpath('pkg', file)
assert '.'.join(value.py__package__()) == package assert '.'.join(value.py__package__()) == package
assert value.is_package() is (path is not None) assert value.is_package() is (path is not None)
if path is not None: if path is not None:
assert value.py__path__() == [os.path.join(pkg_zip_path, path)] assert value.py__path__() == [str(pkg_zip_path.joinpath(path))]
def test_find_module_not_package_zipped(Script, inference_state, environment): def test_find_module_not_package_zipped(Script, inference_state, environment):
@@ -103,7 +104,7 @@ def test_find_module_not_package_zipped(Script, inference_state, environment):
assert len(script.complete()) == 1 assert len(script.complete()) == 1
file_io, is_package = inference_state.compiled_subprocess.get_module_info( file_io, is_package = inference_state.compiled_subprocess.get_module_info(
sys_path=sys_path, sys_path=map(str, sys_path),
string='not_pkg', string='not_pkg',
full_name='not_pkg' full_name='not_pkg'
) )
@@ -435,8 +436,8 @@ def test_pre_defined_imports_module(Script, environment, name):
module = Script('', path=path)._get_module_context() module = Script('', path=path)._get_module_context()
assert module.string_names == (name,) assert module.string_names == (name,)
assert module.inference_state.builtins_module.py__file__() != path assert str(module.inference_state.builtins_module.py__file__()) != path
assert module.inference_state.typing_module.py__file__() != path assert str(module.inference_state.typing_module.py__file__()) != path
@pytest.mark.parametrize('name', ('builtins', 'typing')) @pytest.mark.parametrize('name', ('builtins', 'typing'))
@@ -449,8 +450,8 @@ def test_import_needed_modules_by_jedi(Script, environment, tmpdir, name):
project=Project('.', sys_path=[tmpdir.strpath] + environment.get_sys_path()), project=Project('.', sys_path=[tmpdir.strpath] + environment.get_sys_path()),
) )
module, = script.infer() module, = script.infer()
assert module._inference_state.builtins_module.py__file__() != module_path assert str(module._inference_state.builtins_module.py__file__()) != module_path
assert module._inference_state.typing_module.py__file__() != module_path assert str(module._inference_state.typing_module.py__file__()) != module_path
def test_import_with_semicolon(Script): def test_import_with_semicolon(Script):

View File

@@ -2,6 +2,7 @@ import os
from glob import glob from glob import glob
import sys import sys
import shutil import shutil
from pathlib import Path, PurePath
import pytest import pytest
@@ -17,9 +18,9 @@ def test_paths_from_assignment(Script):
return set(sys_path._paths_from_assignment(script._get_module_context(), expr_stmt)) return set(sys_path._paths_from_assignment(script._get_module_context(), expr_stmt))
# Normalize paths for Windows. # Normalize paths for Windows.
path_a = os.path.abspath('/foo/a') path_a = PurePath('/foo/a')
path_b = os.path.abspath('/foo/b') path_b = PurePath('/foo/b')
path_c = os.path.abspath('/foo/c') path_c = PurePath('/foo/c')
assert paths('sys.path[0:0] = ["a"]') == {path_a} assert paths('sys.path[0:0] = ["a"]') == {path_a}
assert paths('sys.path = ["b", 1, x + 3, y, "c"]') == {path_b, path_c} assert paths('sys.path = ["b", 1, x + 3, y, "c"]') == {path_b, path_c}
@@ -105,5 +106,5 @@ def test_transform_path_to_dotted(sys_path_, module_path, expected, is_package):
# transform_path_to_dotted expects normalized absolute paths. # transform_path_to_dotted expects normalized absolute paths.
sys_path_ = [os.path.abspath(path) for path in sys_path_] sys_path_ = [os.path.abspath(path) for path in sys_path_]
module_path = os.path.abspath(module_path) module_path = os.path.abspath(module_path)
assert sys_path.transform_path_to_dotted(sys_path_, module_path) \ assert sys_path.transform_path_to_dotted(sys_path_, Path(module_path)) \
== (expected, is_package) == (expected, is_package)