コード例 #1
0
    def test_sync_properties(self) -> None:
        """ Tests `sync_properties` with `call=False` """

        with TemporaryDirectory() as tempdir:
            (
                input_filename,
                input_str,
                output_filename,
                output_str,
            ) = populate_files(tempdir)

            self.assertIsNone(
                sync_properties(
                    input_filename=input_filename,
                    input_params=("Foo.g.f", ),
                    input_eval=False,
                    output_filename=output_filename,
                    output_params=("f.h", ),
                ))

            self.run_sync_properties_test(
                input_filename,
                input_str,
                output_filename,
                ast.parse(
                    output_str.replace("h: Literal['b']", "f: Literal['a']")),
            )
コード例 #2
0
    def test_sync_properties_output_param_wrap_subscript(self) -> None:
        """ Tests `sync_properties` with `output_param_wrap` set when replacement_node is subscript and !input_eval """

        with TemporaryDirectory() as tempdir:
            (
                input_filename,
                input_str,
                output_filename,
                output_str,
            ) = populate_files(
                tempdir,
                input_str="a = tuple(range(5))",
                output_str="def j(k):\n"
                "{tab}pass\n".format(tab=tab),
            )

            self.assertIsNone(
                sync_properties(
                    input_filename=input_filename,
                    input_params=("a", ),
                    input_eval=False,
                    output_filename=output_filename,
                    output_params=("j.k", ),
                    output_param_wrap=None,
                ))

            with open(output_filename, "rt") as f:
                # Technically this produces an invalid AST, but we don't care… `input_eval is False`
                self.assertEqual(
                    f.read().rstrip(),
                    output_str.replace("(k)", "(a: tuple(range(5)))").rstrip(),
                )
コード例 #3
0
    def test_sync_properties_output_param_wrap_subscript_eval0(self) -> None:
        """ Tests `sync_properties` with `output_param_wrap` set when replacement_node is subscript """

        with TemporaryDirectory() as tempdir:
            (
                input_filename,
                input_str,
                output_filename,
                output_str,
            ) = populate_files(tempdir,
                               input_str="a = tuple(range(5))",
                               output_str="def j(k): pass")

            self.assertIsNone(
                sync_properties(
                    input_filename=input_filename,
                    input_params=("a", ),
                    input_eval=True,
                    output_filename=output_filename,
                    output_params=("j.k", ),
                    output_param_wrap=None,
                ))

            self.run_sync_properties_test(
                input_filename=input_filename,
                output_filename=output_filename,
                input_str=input_str,
                gold=ast.parse(
                    output_str.replace("(k)", "(k: Literal[0, 1, 2, 3, 4])")),
            )
コード例 #4
0
    def test_sync_properties_output_param_wrap(self) -> None:
        """ Tests `sync_properties` with `output_param_wrap` set """

        with TemporaryDirectory() as tempdir:
            (
                input_filename,
                input_str,
                output_filename,
                output_str,
            ) = populate_files(tempdir)

            self.assertIsNone(
                sync_properties(
                    input_filename=input_filename,
                    input_params=("Foo.g.f", ),
                    input_eval=False,
                    output_filename=output_filename,
                    output_params=("f.h", ),
                    output_param_wrap=
                    "Optional[List[Union[{output_param}, str]]]",
                ))

            self.run_sync_properties_test(
                input_filename=input_filename,
                output_filename=output_filename,
                input_str=input_str,
                gold=ast.parse(
                    output_str.replace(
                        "h: Literal['b']",
                        "f: Optional[List[Union[Literal['a'], str]]]")),
            )
コード例 #5
0
    def test_sync_properties_output_param_wrap_no_type(self) -> None:
        """ Tests `sync_properties` with `output_param_wrap` set when replacement_node has no type """

        with TemporaryDirectory() as tempdir:
            (input_filename, input_str, output_filename, output_str,) = populate_files(
                tempdir,
                output_str=(
                    "from typing import Literal\n\n"
                    "class Foo(object):\n"
                    "{tab}def f(h):\n"
                    "{tab}{tab}pass".format(tab=tab)
                ),
            )

            self.assertIsNone(
                sync_properties(
                    input_filename=input_filename,
                    input_params=("Foo.g.f",),
                    input_eval=False,
                    output_filename=output_filename,
                    output_params=("Foo.f.h",),
                    output_param_wrap="Optional[List[Union[{output_param}, str]]]",
                )
            )

            self.run_sync_properties_test(
                input_filename=input_filename,
                output_filename=output_filename,
                input_str=input_str,
                gold=ast.parse(
                    output_str.replace(
                        "(h)", "(f: Optional[List[Union[Literal['a'], str]]])"
                    )
                ),
            )
コード例 #6
0
    def test_sync_properties_output_param_wrap_no_annotation(self) -> None:
        """ Tests `sync_properties` with `output_param_wrap` set when type annotation isn't being replaced """

        with TemporaryDirectory() as tempdir:
            (input_filename, input_str, output_filename, output_str,) = populate_files(
                tempdir,
                input_str=(
                    "from typing import Literal\n\n"
                    "class Foo(object):\n"
                    "{tab}def g(f):\n"
                    "{tab}{tab}pass".format(tab=tab)
                ),
            )

            self.assertIsNone(
                sync_properties(
                    input_filename=input_filename,
                    input_params=("Foo.g.f",),
                    input_eval=False,
                    output_filename=output_filename,
                    output_params=("f.h",),
                    output_param_wrap="Optional[List[Union[{output_param}, str]]]",
                )
            )

            self.run_sync_properties_test(
                input_filename=input_filename,
                output_filename=output_filename,
                input_str=input_str,
                gold=ast.parse(output_str.replace("h: Literal['b']", "f")),
            )
コード例 #7
0
    def test_sync_properties_eval(self) -> None:
        """ Tests `sync_properties` with `call=True` """

        with open(
            os.path.join(
                os.path.dirname(
                    os.path.dirname(
                        resource_filename(modules[__name__].__name__, "__init__.py")
                    )
                ),
                "tests",
                "mocks",
                "eval.py",
            ),
            "rt",
        ) as f:
            eval_mock_str = f.read()

        with TemporaryDirectory() as tempdir:
            (
                input_filename,
                input_str,
                output_filename,
                output_str,
            ) = populate_files(tempdir, input_str=eval_mock_str)

            self.assertIsNone(
                sync_properties(
                    input_filename=input_filename,
                    input_params=("get_modules",),
                    input_eval=True,
                    output_filename=output_filename,
                    output_params=("f.h",),
                )
            )

            self.run_sync_properties_test(
                input_filename=input_filename,
                output_filename=output_filename,
                input_str=eval_mock_str,
                gold=ast.parse(
                    output_str.replace("h: Literal['b']", "h: Literal['mocks']")
                ),
            )
コード例 #8
0
    def test_sync_properties_eval_fails(self) -> None:
        """ Tests `sync_properties` fails with `call=True` and dots """
        with TemporaryDirectory() as tempdir:
            input_filename = os.path.join(tempdir, "input_.py")
            output_filename = os.path.join(tempdir, "input_str.py")

            open(input_filename, "wt").close()
            open(output_filename, "wt").close()

            self.assertRaises(
                NotImplementedError,
                lambda: sync_properties(
                    input_filename=input_filename,
                    input_params=("foo.bar", ),
                    input_eval=True,
                    output_filename=output_filename,
                    output_params=("f.h", ),
                ),
            )
コード例 #9
0
    def test_sync_properties_output_param_wrap_subscript_eval1(self) -> None:
        """ Tests `sync_properties` with `output_param_wrap` set when replacement_node is subscript """

        with TemporaryDirectory() as tempdir:
            (
                input_filename,
                input_str,
                output_filename,
                output_str,
            ) = populate_files(
                tempdir,
                input_str="import pip\n"
                "c = { attr: getattr(pip, attr)"
                "      for attr in dir(pip)"
                "      if attr in frozenset(('__version__', '__name__')) }\n"
                "a = tuple(sorted(c.keys()))\n",
                output_str="class C(object):\n"
                "{tab}def j(k: str):\n"
                "{tab}{tab}pass\n".format(tab=tab),
            )

            self.assertIsNone(
                sync_properties(
                    input_filename=input_filename,
                    input_params=("a", ),
                    input_eval=True,
                    output_filename=output_filename,
                    output_params=("C.j.k", ),
                    output_param_wrap=None,
                ))

            self.run_sync_properties_test(
                input_filename=input_filename,
                output_filename=output_filename,
                input_str=input_str,
                gold=ast.parse(
                    output_str.replace(
                        "(k: str)",
                        "(k: Literal['__name__', '__version__'])")),
            )
コード例 #10
0
    def test_sync_properties_output_param_wrap_fails(self) -> None:
        """ Tests `sync_properties` fails with `output_param_wrap` set when replacement_node is unknown """

        with TemporaryDirectory() as tempdir:
            (
                input_filename,
                input_str,
                output_filename,
                output_str,
            ) = populate_files(tempdir, input_str="local = locals()")

            self.assertRaises(
                NotImplementedError,
                lambda: sync_properties(
                    input_filename=input_filename,
                    input_params=("local",),
                    input_eval=False,
                    output_filename=output_filename,
                    output_params=("f.h",),
                    output_param_wrap="Optional[List[Union[{output_param}, str]]]",
                ),
            )
コード例 #11
0
def main(cli_argv=None, return_args=False):
    """
    Run the CLI parser

    :param cli_argv: CLI arguments. If None uses `sys.argv`.
    :type cli_argv: ```Optional[List[str]]```

    :param return_args: Primarily use is for tests. Returns the args rather than executing anything.
    :type return_args: ```bool```

    :returns: the args if `return_args`, else None
    :rtype: ```Optional[Namespace]```
    """
    _parser = _build_parser()
    args = _parser.parse_args(args=cli_argv)
    command = args.command
    args_dict = {k: v for k, v in vars(args).items() if k != "command"}
    if command == "sync":
        args = Namespace(
            **{
                k:
                v if k == "truth" or isinstance(v, list) or v is None else [v]
                for k, v in args_dict.items()
            })

        truth_file = getattr(args, pluralise(args.truth))
        if truth_file is None:
            _parser.error("--truth must be an existent file. Got: None")
        else:
            truth_file = truth_file[0]

        truth_file = path.realpath(path.expanduser(truth_file))

        number_of_files = sum(
            len(val) for key, val in vars(args).items()
            if isinstance(val, list) and not key.endswith("_names"))

        if number_of_files < 2:
            _parser.error(
                "Two or more of `--argparse-function`, `--class`, and `--function` must"
                " be specified")
        elif truth_file is None or not path.isfile(truth_file):
            _parser.error("--truth must be an existent file. Got: {!r}".format(
                truth_file))

        return args if return_args else ground_truth(args, truth_file)
    elif command == "sync_properties":
        for fname in "input_filename", "output_filename":
            if path.isfile(getattr(args, fname)):
                setattr(args, fname,
                        path.realpath(path.expanduser(getattr(args, fname))))
        if args.input_filename is None or not path.isfile(args.input_filename):
            _parser.error(
                "--input-file must be an existent file. Got: {!r}".format(
                    args.input_filename))
        elif args.output_filename is None or not path.isfile(
                args.output_filename):
            _parser.error(
                "--output-file must be an existent file. Got: {!r}".format(
                    args.output_filename))
        sync_properties(**args_dict)
    elif command == "gen":
        if path.isfile(args.output_filename):
            raise IOError(
                "File exists and this is a destructive operation. Delete/move {!r} then"
                " rerun.".format(args.output_filename))
        gen(**args_dict)