Example #1
0
def lint(files, check_only):
    """Run flake8, isort and (on Python >=3.6) black."""
    context = _load_project_context()
    source_path = get_source_dir(context.project_path)
    files = files or (
        str(source_path / "tests"),
        str(source_path / context.package_name),
    )

    try:
        # pylint: disable=import-outside-toplevel, unused-import
        import flake8  # noqa
        import isort  # noqa
        import black  # noqa
    except ImportError as exc:
        raise KedroCliError(
            NO_DEPENDENCY_MESSAGE.format(module=exc.name,
                                         src=str(source_path)))

    python_call("black", ("--check", ) + files if check_only else files)
    python_call("flake8", ("--max-line-length=88", ) + files)

    check_flag = ("-c", ) if check_only else ()
    python_call("isort",
                (*check_flag, "-rc", "-tc", "-up", "-fgw=0", "-m=3", "-w=88") +
                files)
Example #2
0
def activate_nbstripout():
    """Install the nbstripout git hook to automatically clean notebooks."""
    context = _load_project_context()
    source_path = get_source_dir(context.project_path)
    secho(
        ("Notebook output cells will be automatically cleared before committing"
         " to git."),
        fg="yellow",
    )

    try:
        # pylint: disable=import-outside-toplevel, unused-import
        import nbstripout  # noqa
    except ImportError:
        raise KedroCliError(
            NO_DEPENDENCY_MESSAGE.format(module="nbstripout",
                                         src=str(source_path)))

    try:
        res = subprocess.run(  # pylint: disable=subprocess-run-check
            ["git", "rev-parse", "--git-dir"],
            stdout=subprocess.PIPE,
            stderr=subprocess.PIPE,
        )
        if res.returncode:
            raise KedroCliError("Not a git repository. Run `git init` first.")
    except FileNotFoundError:
        raise KedroCliError("Git executable not found. Install Git first.")

    call(["nbstripout", "--install"])
Example #3
0
def install():
    """Install project dependencies from both requirements.txt
    and environment.yml (optional)."""
    # we cannot use `context.project_path` as in other commands since
    # context instantiation might break due to missing dependencies
    # we attempt to install here
    source_path = get_source_dir(Path.cwd())

    if (source_path / "environment.yml").is_file():
        call([
            "conda",
            "install",
            "--file",
            str(source_path / "environment.yml"),
            "--yes",
        ])

    pip_command = [
        "install", "-U", "-r",
        str(source_path / "requirements.txt")
    ]

    if os.name == "posix":
        python_call("pip", pip_command)
    else:
        command = [sys.executable, "-m", "pip"] + pip_command
        subprocess.Popen(command, creationflags=subprocess.CREATE_NEW_CONSOLE)
Example #4
0
def install(compile_flag):
    """Install project dependencies from both requirements.txt
    and environment.yml (optional)."""
    # we cannot use `context.project_path` as in other commands since
    # context instantiation might break due to missing dependencies
    # we attempt to install here
    source_path = get_source_dir(Path.cwd())
    environment_yml = source_path / "environment.yml"
    requirements_in = source_path / "requirements.in"
    requirements_txt = source_path / "requirements.txt"

    if environment_yml.is_file():
        call(["conda", "install", "--file", str(environment_yml), "--yes"])

    default_compile = bool(compile_flag is None and not requirements_in.is_file())
    do_compile = compile_flag or default_compile
    if do_compile:
        _build_reqs(source_path)

    pip_command = ["install", "-U", "-r", str(requirements_txt)]

    if os.name == "posix":
        python_call("pip", pip_command)
    else:
        command = [sys.executable, "-m", "pip"] + pip_command
        subprocess.Popen(command, creationflags=subprocess.CREATE_NEW_CONSOLE)
    secho("Requirements installed!", fg="green")
Example #5
0
def convert_notebook(all_flag, overwrite_flag, filepath, env):
    """Convert selected or all notebooks found in a Kedro project
    to Kedro code, by exporting code from the appropriately-tagged cells:
    Cells tagged as `node` will be copied over to a Python file matching
    the name of the notebook, under `<source_dir>/<package_name>/nodes`.
    *Note*: Make sure your notebooks have unique names!
    FILEPATH: Path(s) to exact notebook file(s) to be converted. Both
    relative and absolute paths are accepted.
    Should not be provided if --all flag is already present.
    """
    context = _load_project_context(env=env)
    _update_ipython_dir(context.project_path)

    source_path = get_source_dir(context.project_path)

    if not filepath and not all_flag:
        secho("Please specify a notebook filepath "
              "or add '--all' to convert all notebooks.")
        sys.exit(1)

    if all_flag:
        # pathlib glob does not ignore hidden directories,
        # whereas Python glob does, which is more useful in
        # ensuring checkpoints will not be included
        pattern = context.project_path / "**" / "*.ipynb"
        notebooks = sorted(
            Path(p) for p in iglob(str(pattern), recursive=True))
    else:
        notebooks = [Path(f) for f in filepath]

    counter = Counter(n.stem for n in notebooks)
    non_unique_names = [name for name, counts in counter.items() if counts > 1]
    if non_unique_names:
        names = ", ".join(non_unique_names)
        raise KedroCliError(
            f"Found non-unique notebook names! Please rename the following: {names}"
        )

    output_dir = source_path / context.package_name / "nodes"
    if not output_dir.is_dir():
        output_dir.mkdir()
        (output_dir / "__init__.py").touch()

    for notebook in notebooks:
        secho(f"Converting notebook '{notebook}'...")
        output_path = output_dir / f"{notebook.stem}.py"

        if output_path.is_file():
            overwrite = overwrite_flag or click.confirm(
                f"Output file {output_path} already exists. Overwrite?",
                default=False,
            )
            if overwrite:
                _export_nodes(notebook, output_path)
        else:
            _export_nodes(notebook, output_path)

    secho("Done!", color="green")
Example #6
0
def test_get_source_dir(tmp_path, fake_kedro_yml, expected_source_dir):
    expected_source_dir = (tmp_path / expected_source_dir).resolve()
    assert fake_kedro_yml.is_file()

    pattern = "This function is now deprecated and will be removed in Kedro 0.17.0"
    with pytest.warns(DeprecationWarning, match=re.escape(pattern)):
        src_dir = get_source_dir(tmp_path)

    assert src_dir == expected_source_dir
Example #7
0
def package():
    """Package the project as a Python egg and wheel."""
    context = _load_project_context()
    source_path = get_source_dir(context.project_path)
    call(
        [sys.executable, "setup.py", "clean", "--all", "bdist_egg"],
        cwd=str(source_path),
    )
    call(
        [sys.executable, "setup.py", "clean", "--all", "bdist_wheel"],
        cwd=str(source_path),
    )
Example #8
0
def test(args):
    """Run the test suite."""
    try:
        # pylint: disable=import-outside-toplevel, unused-import
        import pytest  # noqa
    except ImportError:
        context = _load_project_context()
        source_path = get_source_dir(context.project_path)
        raise KedroCliError(
            NO_DEPENDENCY_MESSAGE.format(module="pytest",
                                         src=str(source_path)))
    else:
        python_call("pytest", args)
Example #9
0
def build_reqs(args):
    """Build the project dependency requirements."""
    # we cannot use `context.project_path` as in other commands since
    # context instantiation might break due to missing dependencies
    # we attempt to install here
    source_path = get_source_dir(Path.cwd())
    _build_reqs(source_path, args)
    secho(
        "Requirements built! Please update requirements.in "
        "if you'd like to make a change in your project's dependencies, "
        "and re-run build-reqs to generate the new requirements.txt.",
        fg="green",
    )
Example #10
0
def build_reqs():
    """Build the project dependency requirements."""
    # we cannot use `context.project_path` as in other commands since
    # context instantiation might break due to missing dependencies
    # we attempt to install here
    source_path = get_source_dir(Path.cwd())
    requirements_path = source_path / "requirements.in"
    if not requirements_path.is_file():
        secho(
            "No requirements.in found. Copying contents from requirements.txt..."
        )
        contents = (source_path / "requirements.txt").read_text()
        requirements_path.write_text(contents)
    python_call("piptools", ["compile", str(requirements_path)])
    secho(("Requirements built! Please update requirements.in "
           "if you'd like to make a change in your project's dependencies, "
           "and re-run build-reqs to generate the new requirements.txt."))
Example #11
0
def build_docs(open_docs):
    """Build the project documentation."""
    context = _load_project_context()
    source_path = get_source_dir(context.project_path)
    python_call("pip", ["install", str(source_path / "[docs]")])
    python_call("pip", ["install", "-r", str(source_path / "requirements.txt")])
    python_call("ipykernel", ["install", "--user", f"--name={context.package_name}"])
    shutil.rmtree("docs/build", ignore_errors=True)
    call(
        [
            "sphinx-apidoc",
            "--module-first",
            "-o",
            "docs/source",
            str(source_path / context.package_name),
        ]
    )
    call(["sphinx-build", "-M", "html", "docs/source", "docs/build", "-a"])
    if open_docs:
        docs_page = (Path.cwd() / "docs" / "build" / "html" / "index.html").as_uri()
        secho(f"Opening {docs_page}")
        webbrowser.open(docs_page)