예제 #1
0
def test_comprehensions():
    assert ({"x"}, {"y"}) == find_names(ast.parse("(x for x in y)"))
    assert ({"x"}, {"x"}) == find_names(ast.parse("(x for x in x)"))
    assert ({"x", "xx"},
            {"xxx"}) == find_names(ast.parse("(x for xx in xxx for x in xx)"))
    assert ({"x", "xx"},
            {"xx",
             "xxx"}) == find_names(ast.parse("(x for x in xx for xx in xxx)"))
예제 #2
0
def check_find_names(code: str,
                     defined: Set[str],
                     undefined: Set[str],
                     confirm: bool = True) -> None:
    assert (defined, undefined) == find_names(ast.parse(code))

    if not confirm:
        return

    exec_locals = {}
    actually_undefined = undefined - set(dir(__import__("builtins")))
    if actually_undefined:
        # If something is actually undefined, we should raise a NameError when we execute
        # (if we hit another exception first, we fix the test!)
        with pytest.raises(NameError) as e:
            exec(code, exec_locals)
        assert re.search(r"name '(\w+)' is not",
                         e.value.args[0]).group(1) in actually_undefined
    else:
        try:
            exec(code, exec_locals)
        except Exception as e:
            # Unlike above, allow this code to fail, but if it fails, it shouldn't be a NameError!
            assert not isinstance(e, NameError)

    exec_locals = set(exec_locals)
    exec_locals -= {"__builtins__", "__annotations__"}
    # In general, we over define things, because we don't deal with scopes and such. So just check
    # a subset relationship holds, we could tighten this check in the future.
    assert exec_locals <= defined
예제 #3
0
def test_basic():
    assert (set(), set("x")) == find_names(ast.parse("x[:3]"))
    assert ({"x"}, set()) == find_names(ast.parse("x = 1"))
    assert ({"x", "y"}, set()) == find_names(ast.parse("x = 1; y = x + 1"))
예제 #4
0
def test_del():
    assert ({"x"}, {"x"}) == find_names(ast.parse("x = 3; del x; x"))
예제 #5
0
def test_args_bad():
    assert ({"f", "x"}, {"x"}) == find_names(ast.parse("f = lambda x: x; x"))
예제 #6
0
def test_args():
    assert ({"f"}, {"x"}) == find_names(ast.parse("f = lambda: x"))
    assert ({"f", "x"}, set()) == find_names(ast.parse("f = lambda x: x"))
    assert ({"f", "x"}, {"y"}) == find_names(ast.parse("f = lambda x: y"))
    assert ({"a", "b", "c", "x", "y", "z"}, set()) == find_names(
        ast.parse("def f(x, y = 0, *z, a, b = 0, **c): ..."))
예제 #7
0
def test_weird_assignments():
    assert ({"x"}, {"x"}) == find_names(ast.parse("x += 1"))
    assert ({"x"}, {"x"}) == find_names(ast.parse("for x in x: pass"))
    assert ({"x", "y"}, {"x", "y"}) == find_names(ast.parse("x, y = x, y"))
    if sys.version_info >= (3, 8):
        assert ({"x"}, {"x"}) == find_names(ast.parse("(x := x)"))
예제 #8
0
def test_builtins():
    assert (set(), {"print"}) == find_names(ast.parse("print(5)"))
    assert ({"print"}, set()) == find_names(ast.parse("print = 5; print(5)"))
예제 #9
0
def test_loops():
    assert ({"x"}, {"y",
                    "print"}) == find_names(ast.parse("for x in y: print(x)"))
    assert (set(), {"x"}) == find_names(ast.parse("while x: pass"))
예제 #10
0
def check_find_names(code: str, defined: Set[str], undefined: Set[str]) -> None:
    assert (defined, undefined) == find_names(ast.parse(code))