mirror of
https://github.com/SpaceVim/SpaceVim.git
synced 2025-02-04 15:40:05 +08:00
198 lines
5.1 KiB
Python
198 lines
5.1 KiB
Python
|
"""
|
||
|
Tests for `api.names`.
|
||
|
"""
|
||
|
|
||
|
from textwrap import dedent
|
||
|
|
||
|
import pytest
|
||
|
|
||
|
|
||
|
def _assert_definition_names(definitions, names):
|
||
|
assert [d.name for d in definitions] == names
|
||
|
|
||
|
|
||
|
def _check_names(get_names, source, names):
|
||
|
definitions = get_names(dedent(source))
|
||
|
_assert_definition_names(definitions, names)
|
||
|
return definitions
|
||
|
|
||
|
|
||
|
def test_get_definitions_flat(get_names):
|
||
|
_check_names(get_names, """
|
||
|
import module
|
||
|
class Class:
|
||
|
pass
|
||
|
def func():
|
||
|
pass
|
||
|
data = None
|
||
|
""", ['module', 'Class', 'func', 'data'])
|
||
|
|
||
|
|
||
|
def test_dotted_assignment(get_names):
|
||
|
_check_names(get_names, """
|
||
|
x = Class()
|
||
|
x.y.z = None
|
||
|
""", ['x', 'z']) # TODO is this behavior what we want?
|
||
|
|
||
|
|
||
|
def test_multiple_assignment(get_names):
|
||
|
_check_names(get_names, "x = y = None", ['x', 'y'])
|
||
|
|
||
|
|
||
|
def test_multiple_imports(get_names):
|
||
|
_check_names(get_names, """
|
||
|
from module import a, b
|
||
|
from another_module import *
|
||
|
""", ['a', 'b'])
|
||
|
|
||
|
|
||
|
def test_nested_definitions(get_names):
|
||
|
definitions = _check_names(get_names, """
|
||
|
class Class:
|
||
|
def f():
|
||
|
pass
|
||
|
def g():
|
||
|
pass
|
||
|
""", ['Class'])
|
||
|
subdefinitions = definitions[0].defined_names()
|
||
|
_assert_definition_names(subdefinitions, ['f', 'g'])
|
||
|
assert [d.full_name for d in subdefinitions] == ['__main__.Class.f', '__main__.Class.g']
|
||
|
|
||
|
|
||
|
def test_nested_class(get_names):
|
||
|
definitions = _check_names(get_names, """
|
||
|
class L1:
|
||
|
class L2:
|
||
|
class L3:
|
||
|
def f(): pass
|
||
|
def f(): pass
|
||
|
def f(): pass
|
||
|
def f(): pass
|
||
|
""", ['L1', 'f'])
|
||
|
subdefs = definitions[0].defined_names()
|
||
|
subsubdefs = subdefs[0].defined_names()
|
||
|
_assert_definition_names(subdefs, ['L2', 'f'])
|
||
|
_assert_definition_names(subsubdefs, ['L3', 'f'])
|
||
|
_assert_definition_names(subsubdefs[0].defined_names(), ['f'])
|
||
|
|
||
|
|
||
|
def test_class_fields_with_all_scopes_false(get_names):
|
||
|
definitions = _check_names(get_names, """
|
||
|
from module import f
|
||
|
g = f(f)
|
||
|
class C:
|
||
|
h = g
|
||
|
|
||
|
def foo(x=a):
|
||
|
bar = x
|
||
|
return bar
|
||
|
""", ['f', 'g', 'C', 'foo'])
|
||
|
C_subdefs = definitions[-2].defined_names()
|
||
|
foo_subdefs = definitions[-1].defined_names()
|
||
|
_assert_definition_names(C_subdefs, ['h'])
|
||
|
_assert_definition_names(foo_subdefs, ['x', 'bar'])
|
||
|
|
||
|
|
||
|
def test_async_stmt_with_all_scopes_false(get_names):
|
||
|
definitions = _check_names(get_names, """
|
||
|
from module import f
|
||
|
import asyncio
|
||
|
|
||
|
g = f(f)
|
||
|
class C:
|
||
|
h = g
|
||
|
def __init__(self):
|
||
|
pass
|
||
|
|
||
|
async def __aenter__(self):
|
||
|
pass
|
||
|
|
||
|
def foo(x=a):
|
||
|
bar = x
|
||
|
return bar
|
||
|
|
||
|
async def async_foo(duration):
|
||
|
async def wait():
|
||
|
await asyncio.sleep(100)
|
||
|
for i in range(duration//100):
|
||
|
await wait()
|
||
|
return duration//100*100
|
||
|
|
||
|
async with C() as cinst:
|
||
|
d = cinst
|
||
|
""", ['f', 'asyncio', 'g', 'C', 'foo', 'async_foo', 'cinst', 'd'])
|
||
|
C_subdefs = definitions[3].defined_names()
|
||
|
foo_subdefs = definitions[4].defined_names()
|
||
|
async_foo_subdefs = definitions[5].defined_names()
|
||
|
cinst_subdefs = definitions[6].defined_names()
|
||
|
_assert_definition_names(C_subdefs, ['h', '__init__', '__aenter__'])
|
||
|
_assert_definition_names(foo_subdefs, ['x', 'bar'])
|
||
|
_assert_definition_names(async_foo_subdefs, ['duration', 'wait', 'i'])
|
||
|
# We treat d as a name outside `async with` block
|
||
|
_assert_definition_names(cinst_subdefs, [])
|
||
|
|
||
|
|
||
|
def test_follow_imports(get_names):
|
||
|
# github issue #344
|
||
|
imp = get_names('import datetime')[0]
|
||
|
assert imp.name == 'datetime'
|
||
|
datetime_names = [str(d.name) for d in imp.defined_names()]
|
||
|
assert 'timedelta' in datetime_names
|
||
|
|
||
|
|
||
|
def test_names_twice(get_names):
|
||
|
code = dedent('''
|
||
|
def lol():
|
||
|
pass
|
||
|
''')
|
||
|
|
||
|
defs = get_names(code)
|
||
|
assert defs[0].defined_names() == []
|
||
|
|
||
|
|
||
|
def test_simple_name(get_names):
|
||
|
defs = get_names('foo', references=True)
|
||
|
assert not defs[0]._name.infer()
|
||
|
|
||
|
|
||
|
def test_no_error(get_names):
|
||
|
code = dedent("""
|
||
|
def foo(a, b):
|
||
|
if a == 10:
|
||
|
if b is None:
|
||
|
print("foo")
|
||
|
a = 20
|
||
|
""")
|
||
|
func_name, = get_names(code)
|
||
|
a, b, a20 = func_name.defined_names()
|
||
|
assert a.name == 'a'
|
||
|
assert b.name == 'b'
|
||
|
assert a20.name == 'a'
|
||
|
assert a20.goto() == [a20]
|
||
|
|
||
|
|
||
|
@pytest.mark.parametrize(
|
||
|
'code, index, is_side_effect', [
|
||
|
('x', 0, False),
|
||
|
('x.x', 0, False),
|
||
|
('x.x', 1, False),
|
||
|
('x.x = 3', 0, False),
|
||
|
('x.x = 3', 1, True),
|
||
|
('def x(x): x.x = 3', 1, False),
|
||
|
('def x(x): x.x = 3', 3, True),
|
||
|
('import sys; sys.path', 0, False),
|
||
|
('import sys; sys.path', 1, False),
|
||
|
('import sys; sys.path', 2, False),
|
||
|
('import sys; sys.path = []', 2, True),
|
||
|
]
|
||
|
)
|
||
|
def test_is_side_effect(get_names, code, index, is_side_effect):
|
||
|
names = get_names(code, references=True, all_scopes=True)
|
||
|
assert names[index].is_side_effect() == is_side_effect
|
||
|
|
||
|
|
||
|
def test_no_defined_names(get_names):
|
||
|
definition, = get_names("x = (1, 2)")
|
||
|
|
||
|
assert not definition.defined_names()
|