def test_find_notebooks(tmp_path, notebook_asset):
    shutil.copy(notebook_asset.path, tmp_path / "the_notebook_0.ipynb")
    shutil.copy(notebook_asset.path, tmp_path / "the_notebook_1.ipynb")
    expected_notebooks = [
        JupyterNotebook.from_file(tmp_path / "the_notebook_0.ipynb"),
        JupyterNotebook.from_file(tmp_path / "the_notebook_1.ipynb"),
    ]

    # Non-notebook files
    (tmp_path / "the_journal.txt").touch()
    with (tmp_path / "the_log.json").open("w", encoding="utf-8") as fp:
        json.dump(
            {
                "LOG ENTRY: SOL 61": "How come Aquaman can control whales?",
                "LOG ENTRY: SOL 381":
                "That makes me a pirate! A space pirate!",
            },
            fp,
        )
    with (tmp_path / SAVE_PROGRESS_INDICATOR_FILE).open(
            "w", encoding="utf-8") as fp:
        fp.write(NbAutoexportConfig().json())

    found_notebooks = find_notebooks(tmp_path)

    assert set(found_notebooks) == set(expected_notebooks)
Exemple #2
0
def test_clean_relative(notebooks_dir, organize_by):
    """ Test that cleaning works relative to current working directory.
    """
    with working_directory(notebooks_dir):
        sentinel_path = Path(SAVE_PROGRESS_INDICATOR_FILE)
        config = NbAutoexportConfig(export_formats=EXPECTED_FORMATS,
                                    organize_by=organize_by)
        with sentinel_path.open("w") as fp:
            fp.write(config.json())

        result = CliRunner().invoke(app, ["clean", "."], input="y")
        assert result.exit_code == 0

        expected_notebooks = [
            JupyterNotebook.from_file(f"{nb}.ipynb")
            for nb in EXPECTED_NOTEBOOKS
        ]
        expected_exports = set(get_expected_exports(expected_notebooks,
                                                    config))

        all_expected = {nb.path
                        for nb in expected_notebooks
                        } | expected_exports | {sentinel_path}
        assert set(Path().glob("**/*")) == all_expected

        # Run clean again, there should be nothing to do
        result_rerun = CliRunner().invoke(app, ["clean", "."])
        assert result_rerun.exit_code == 0
        assert result_rerun.stdout.strip().endswith(
            "No files identified for cleaning. Exiting.")
Exemple #3
0
def test_clean(notebooks_dir, need_confirmation, organize_by):
    sentinel_path = notebooks_dir / SAVE_PROGRESS_INDICATOR_FILE
    config = NbAutoexportConfig(export_formats=EXPECTED_FORMATS,
                                organize_by=organize_by)
    with sentinel_path.open("w") as fp:
        fp.write(config.json())

    if need_confirmation:
        result = CliRunner().invoke(app, ["clean", str(notebooks_dir)],
                                    input="y")
    else:
        result = CliRunner().invoke(
            app, ["clean", str(notebooks_dir), "--yes"])
    assert result.exit_code == 0

    expected_notebooks = [
        JupyterNotebook.from_file(notebooks_dir / f"{nb}.ipynb")
        for nb in EXPECTED_NOTEBOOKS
    ]
    expected_exports = set(get_expected_exports(expected_notebooks, config))

    all_expected = {nb.path
                    for nb in expected_notebooks
                    } | expected_exports | {sentinel_path}
    assert set(notebooks_dir.glob("**/*")) == all_expected

    # Run clean again, there should be nothing to do
    result_rerun = CliRunner().invoke(app, ["clean", str(notebooks_dir)])
    assert result_rerun.exit_code == 0
    assert result_rerun.stdout.strip().endswith(
        "No files identified for cleaning. Exiting.")
Exemple #4
0
def notebooks_dir(tmp_path, notebook_asset):
    notebooks = EXPECTED_NOTEBOOKS + [UNEXPECTED_NOTEBOOK]
    export_formats = [
        ExportFormat(fmt) for fmt in EXPECTED_FORMATS + [UNEXPECTED_FORMAT]
    ]
    for nb_name in notebooks:
        shutil.copy(notebook_asset.path, tmp_path / f"{nb_name}.ipynb")
        nb = JupyterNotebook.from_file(tmp_path / f"{nb_name}.ipynb")

        # organize_by notebook
        nb_subfolder = tmp_path / nb.name
        nb_subfolder.mkdir()
        for fmt in export_formats:
            (nb_subfolder / f"{nb.name}{get_extension(nb, fmt)}").touch()

        # organize_by extension
        for fmt in export_formats:
            format_subfolder = tmp_path / fmt.value
            format_subfolder.mkdir(exist_ok=True)
            (format_subfolder / f"{nb.name}{get_extension(nb, fmt)}").touch()

        # add latex image dir
        (nb_subfolder / f"{nb.name}_files").mkdir()
        (nb_subfolder / f"{nb.name}_files" / f"{nb.name}_1_1.png").touch()
        (tmp_path / "latex" / f"{nb.name}_files").mkdir()
        (tmp_path / "latex" / f"{nb.name}_files" /
         f"{nb.name}_1_1.png").touch()

    (tmp_path / f"{UNEXPECTED_NOTEBOOK}.ipynb").unlink()

    return tmp_path
Exemple #5
0
def test_export_notebook(notebooks_dir, organize_by):
    """Test that export notebook works. Explicitly write out expected files, because tests for
    get_expected_exports will compare against export_notebook.
    """
    notebook = JupyterNotebook.from_file(notebooks_dir / "the_notebook.ipynb")
    config = NbAutoexportConfig(export_formats=EXPORT_FORMATS_TO_TEST,
                                organize_by=organize_by)
    export_notebook(notebook.path, config)

    expected_exports = set()
    for fmt in EXPORT_FORMATS_TO_TEST:
        if organize_by == "extension":
            subfolder = notebooks_dir / fmt.value
        elif organize_by == "notebook":
            subfolder = notebooks_dir / notebook.name
        extension = get_extension(notebook, fmt)

        expected_exports.add(subfolder)  # subfolder
        expected_exports.add(subfolder /
                             f"{notebook.name}{extension}")  # export file

        if fmt in FORMATS_WITH_IMAGE_DIR:
            image_subfolder = subfolder / f"{notebook.name}_files"

            expected_exports.add(image_subfolder)  # image subdir
            expected_exports.add(image_subfolder /
                                 f"{notebook.name}_1_1.png")  # image file

    all_expected = {notebook.path} | expected_exports
    assert all_expected.issubset(set(notebooks_dir.glob("**/*")))
def test_clean_exclude(notebooks_dir):
    """Test that cleaning works with exclude"""
    with working_directory(notebooks_dir):
        # Set up subdirectory
        subdir = Path("subdir")
        subdir.mkdir()
        for subfile in Path().iterdir():
            shutil.move(str(subfile), str(subdir))

        # Set up extra files
        extra_files = [
            subdir / "keep.txt",
            subdir / "delete.txt",
            subdir / "images" / "keep.jpg",
            subdir / "images" / "delete.png",
            subdir / "pictures" / "delete.jpg",
            subdir / "keep.md",
            subdir / "docs" / "keep.md",
        ]
        for extra_file in extra_files:
            extra_file.parent.mkdir(exist_ok=True)
            extra_file.touch()

        sentinel_path = subdir / SAVE_PROGRESS_INDICATOR_FILE
        config = NbAutoexportConfig(
            export_formats=EXPECTED_FORMATS,
            organize_by="extension",
            clean=CleanConfig(exclude=["keep.txt", "images/*.jpg"]),
        )
        with sentinel_path.open("w", encoding="utf-8") as fp:
            fp.write(config.json())

        command = ["clean", "subdir", "-e", "**/*.md"]
        result = CliRunner().invoke(app, command, input="y")
        assert result.exit_code == 0

        expected_notebooks = [
            JupyterNotebook.from_file(subdir / f"{nb}.ipynb")
            for nb in EXPECTED_NOTEBOOKS
        ]
        expected_exports = set(get_expected_exports(expected_notebooks,
                                                    config))
        expected_extra = {
            extra_file
            for extra_file in extra_files if extra_file.match("keep.*")
        } | {subdir / "images", subdir / "docs"}

        all_expected = ({nb.path
                         for nb in expected_notebooks}
                        | expected_exports
                        | {sentinel_path}
                        | expected_extra)
        assert set(subdir.glob("**/*")) == all_expected

        # Run clean again, there should be nothing to do
        result_rerun = CliRunner().invoke(app, command)
        assert result_rerun.exit_code == 0
        assert result_rerun.stdout.strip().endswith(
            "No files identified for cleaning. Exiting.")
Exemple #7
0
def get_extension(notebook: JupyterNotebook,
                  export_format: ExportFormat) -> str:
    """Given a notebook and export format, return expected export file extension.

    Args:
        notebook (JupyterNotebook): notebook to determine extension for
        export_format (str): export format name

    Returns:
        str: file extension, e.g., '.py'
    """
    # Script format needs notebook to determine appropriate language's extension
    if ExportFormat(export_format) == ExportFormat.script:
        return notebook.get_script_extension()

    exporter = get_exporter(ExportFormat(export_format).value)

    if ExportFormat(export_format) == ExportFormat.notebook:
        return f".nbconvert{exporter().file_extension}"
    return exporter().file_extension
Exemple #8
0
def notebook_asset():
    return JupyterNotebook.from_file(
        Path(__file__).parent / "assets" / "the_notebook.ipynb")