def RemoveMutableParameters(ast): """Change all mutable parameters in a pytd AST to a non-mutable form.""" ast = ast.Visit(optimize.AbsorbMutableParameters()) ast = ast.Visit(optimize.CombineContainers()) ast = ast.Visit(optimize.MergeTypeParameters()) ast = ast.Visit(visitors.AdjustSelf(force=True)) return ast
def testCombineDifferentLengthTuples(self): src = textwrap.dedent(""" x = ... # type: tuple[int] or tuple[int, str] """) expected = textwrap.dedent(""" x = ... # type: tuple[int or str, ...] """) new_src = self.ApplyVisitorToString(src, optimize.CombineContainers()) self.AssertSourceEquals(new_src, expected)
def testCombineContainersMultiLevel(self): src = textwrap.dedent(""" v = ... # type: list[tuple[long or int, ...]] or list[tuple[float or bool, ...]] """) expected = textwrap.dedent(""" v = ... # type: list[tuple[long or int or float or bool, ...]] """) new_src = self.ApplyVisitorToString(src, optimize.CombineContainers()) self.AssertSourceEquals(new_src, expected)
def test_combine_different_length_tuples(self): src = pytd_src(""" x = ... # type: Union[tuple[int], tuple[int, str]] """) expected = pytd_src(""" x = ... # type: tuple[Union[int, str], ...] """) new_src = self.ApplyVisitorToString(src, optimize.CombineContainers()) self.AssertSourceEquals(new_src, expected)
def test_combine_containers_multi_level(self): src = pytd_src(""" v = ... # type: Union[list[tuple[Union[long, int], ...]], list[tuple[Union[float, bool], ...]]] """) expected = pytd_src(""" v = ... # type: list[tuple[Union[long, int, float, bool], ...]] """) new_src = self.ApplyVisitorToString(src, optimize.CombineContainers()) self.AssertSourceEquals(new_src, expected)
def RemoveMutableParameters(ast): """Change all mutable parameters in a pytd AST to a non-mutable form.""" # late import, because optimize uses utils.py. from pytype.pytd import optimize # pylint: disable=g-import-not-at-top ast = ast.Visit(optimize.AbsorbMutableParameters()) ast = ast.Visit(optimize.CombineContainers()) ast = ast.Visit(optimize.MergeTypeParameters()) ast = ast.Visit(visitors.AdjustSelf(force=True)) return ast
def testCombineDifferentLengthCallables(self): src = textwrap.dedent(""" from typing import Callable x = ... # type: Callable[[int], str] or Callable[[int, int], str] """) expected = textwrap.dedent(""" from typing import Callable x = ... # type: Callable[..., str] """) new_src = self.ApplyVisitorToString(src, optimize.CombineContainers()) self.AssertSourceEquals(new_src, expected)
def test_combine_different_length_callables(self): src = pytd_src(""" from typing import Callable x = ... # type: Union[Callable[[int], str], Callable[[int, int], str]] """) expected = pytd_src(""" from typing import Callable x = ... # type: Callable[..., str] """) new_src = self.ApplyVisitorToString(src, optimize.CombineContainers()) self.AssertSourceEquals(new_src, expected)
def test_absorb_mutable_parameters_from_methods(self): # This is a test for intermediate data. See AbsorbMutableParameters class # pydoc about how AbsorbMutableParameters works on methods. src = pytd_src(""" from typing import Any T = TypeVar('T') NEW = TypeVar('NEW') class MyClass(typing.Generic[T], object): def append(self, x: NEW) -> Any: self = MyClass[Union[T, NEW]] """) tree = self.Parse(src) new_tree = tree.Visit(optimize.AbsorbMutableParameters()) new_tree = new_tree.Visit(optimize.CombineContainers()) self_type = new_tree.Lookup("MyClass").Lookup( "append").signatures[0].params[0].type self.assertEqual(pytd_utils.Print(self_type), "MyClass[Union[T, NEW]]")
def testAbsorbMutableParameters(self): src = textwrap.dedent(""" def popall(x: list[?]) -> ?: x := list[nothing] def add_float(x: list[int]) -> ?: x := list[int or float] def f(x: list[int]) -> ?: x := list[int or float] """) expected = textwrap.dedent(""" def popall(x: list[?]) -> ? def add_float(x: list[int or float]) -> ? def f(x: list[int or float]) -> ? """) tree = self.Parse(src) new_tree = tree.Visit(optimize.AbsorbMutableParameters()) new_tree = new_tree.Visit(optimize.CombineContainers()) self.AssertSourceEquals(new_tree, expected)
def testCombineContainers(self): src = textwrap.dedent(""" def f(x: list[int] or list[float]) -> ? def g(x: list[int] or str or list[float] or set[int] or long) -> ? def h(x: list[int] or list[str] or set[int] or set[float]) -> ? def i(x: list[int] or list[int]) -> ? def j(x: dict[int, float] or dict[float, int]) -> ? def k(x: dict[int, bool] or list[int] or dict[bool, int] or list[bool]) -> ? """) expected = textwrap.dedent(""" def f(x: list[float]) -> ?: ... def g(x: list[float] or str or set[int] or long) -> ?: ... def h(x: list[int or str] or set[float]) -> ?: ... def i(x: list[int]) -> ?: ... def j(x: dict[float, float]) -> ?: ... def k(x: dict[int or bool, bool or int] or list[int or bool]) -> ?: ... """) new_src = self.ApplyVisitorToString(src, optimize.CombineContainers()) self.AssertSourceEquals(new_src, expected)
def testAbsorbMutableParametersFromMethods(self): # This is a test for intermediate data. See AbsorbMutableParameters class # pydoc about how AbsorbMutableParameters works on methods. src = textwrap.dedent(""" T = TypeVar('T') NEW = TypeVar('NEW') class MyClass(typing.Generic[T], object): def append(self, x: NEW) -> ?: self := MyClass[T or NEW] """) expected = textwrap.dedent(""" T = TypeVar('T') NEW = TypeVar('NEW') class MyClass(typing.Generic[T], object): def append(self: MyClass[T or NEW], x: NEW) -> ? """) tree = self.Parse(src) new_tree = tree.Visit(optimize.AbsorbMutableParameters()) new_tree = new_tree.Visit(optimize.CombineContainers()) self.AssertSourceEquals(new_tree, expected)
def test_absorb_mutable_parameters(self): src = pytd_src(""" from typing import Any def popall(x: list[Any]) -> Any: x = list[nothing] def add_float(x: list[int]) -> Any: x = list[Union[int, float]] def f(x: list[int]) -> Any: x = list[Union[int, float]] """) expected = pytd_src(""" from typing import Any def popall(x: list[Any]) -> Any: ... def add_float(x: list[Union[int, float]]) -> Any: ... def f(x: list[Union[int, float]]) -> Any: ... """) tree = self.Parse(src) new_tree = tree.Visit(optimize.AbsorbMutableParameters()) new_tree = new_tree.Visit(optimize.CombineContainers()) self.AssertSourceEquals(new_tree, expected)
def test_combine_containers(self): src = pytd_src(""" from typing import Any def f(x: Union[list[int], list[float]]) -> Any: ... def g(x: Union[list[int], str, list[float], set[int], long]) -> Any: ... def h(x: Union[list[int], list[str], set[int], set[float]]) -> Any: ... def i(x: Union[list[int], list[int]]) -> Any: ... def j(x: Union[dict[int, float], dict[float, int]]) -> Any: ... def k(x: Union[dict[int, bool], list[int], dict[bool, int], list[bool]]) -> Any: ... """) expected = pytd_src(""" from typing import Any def f(x: list[float]) -> Any: ... def g(x: Union[list[float], str, set[int], long]) -> Any: ... def h(x: Union[list[Union[int, str]], set[float]]) -> Any: ... def i(x: list[int]) -> Any: ... def j(x: dict[float, float]) -> Any: ... def k(x: Union[dict[Union[int, bool], Union[bool, int]], list[Union[int, bool]]]) -> Any: ... """) new_src = self.ApplyVisitorToString(src, optimize.CombineContainers()) self.AssertSourceEquals(new_src, expected)
def test_absorb_mutable_parameters_from_methods(self): # This is a test for intermediate data. See AbsorbMutableParameters class # pydoc about how AbsorbMutableParameters works on methods. src = pytd_src(""" from typing import Any T = TypeVar('T') NEW = TypeVar('NEW') class MyClass(typing.Generic[T], object): def append(self, x: NEW) -> Any: self = MyClass[Union[T, NEW]] """) expected = pytd_src(""" from typing import Any T = TypeVar('T') NEW = TypeVar('NEW') class MyClass(typing.Generic[T], object): def append(self: MyClass[Union[T, NEW]], x: NEW) -> Any: ... """) tree = self.Parse(src) new_tree = tree.Visit(optimize.AbsorbMutableParameters()) new_tree = new_tree.Visit(optimize.CombineContainers()) self.AssertSourceEquals(new_tree, expected)