Repository: executablebooks/jupyter-book
File: jupyter_book/utils.py (Python)

Code before:
        url = op.splitext(url)[0] + ".html"
    return url


def _clean_markdown_cells(ntbk):
    """Clean up cell text of an nbformat NotebookNode."""
    # Remove '#' from the end of markdown headers
    for cell in ntbk.cells:
        if cell.cell_type == "markdown":
            cell_lines = cell.source.split("\n")
            for ii, line in enumerate(cell_lines):
                if line.startswith("#"):
                    cell_lines[ii] = line.rstrip("#").rstrip()
            cell.source = "\n".join(cell_lines)
    return ntbk


def _file_newer_than(path1, path2):
    """Check whether file at path1 is newer than path2."""
    return os.stat(path1).st_mtime > os.stat(path2).st_mtime


def _minor_release(version):
    """Excludes the patch release from a version number, such that
    only major and minor versions face strict matching."""
    return '.'.join(version.split('.')[:-1])


def _check_book_versions(path_book):
    """Check whether the version of a book matches the version of the
    CLI that's building it."""

    with open(op.join(path_book, "_config.yml"), 'r') as ff:
        config_version = yaml.safe_load(ff.read()).get(
            "jupyter_book_version"
        )

    if config_version is None:
        raise _error(
            "Couldn't find the version for your Jupyter Book.\n"
            f"Try upgrading it with `jupyter-book upgrade {path_book}"
        )

    if _minor_release(config_version) != _minor_release(__version__):
        raise _error(
            f"The version of the book you are modifying doesn't match the\n"
            "version of the command-line tool that you're using. Please run\n"
            "\n"
            f"    jupyter-book upgrade {path_book} \n"
            "\n"
            "to upgrade your book to the CLI version.\n"

Review comment (suggestion):
I think a slightly more readable version of this could be:

```suggestion
    major_minor_version = version.rsplit('.', 1)[0])
    if len(major_minor_version .split('.')) != 2:
        raise ValueError("Version doesn't conform to `major.minor.patch` format.")
    return major_minor_version 
```

so if we have a version like 0.6.1dev0, this should return only `0.6`

Code after:
        url = op.splitext(url)[0] + ".html"
    return url


def _clean_markdown_cells(ntbk):
    """Clean up cell text of an nbformat NotebookNode."""
    # Remove '#' from the end of markdown headers
    for cell in ntbk.cells:
        if cell.cell_type == "markdown":
            cell_lines = cell.source.split("\n")
            for ii, line in enumerate(cell_lines):
                if line.startswith("#"):
                    cell_lines[ii] = line.rstrip("#").rstrip()
            cell.source = "\n".join(cell_lines)
    return ntbk


def _file_newer_than(path1, path2):
    """Check whether file at path1 is newer than path2."""
    return os.stat(path1).st_mtime > os.stat(path2).st_mtime


def _minor_release(version):
    """Excludes the patch release from a version number, such that
    only major and minor versions face strict matching."""
    major_minor_version = version.rsplit('.', 1)[0]
    if len(major_minor_version .split('.')) != 2:
        raise ValueError("Version doesn't conform to `major.minor.patch` format.")
    return major_minor_version


def _check_book_versions(path_book):
    """Check whether the version of a book matches the version of the
    CLI that's building it.
    """

    with open(op.join(path_book, "_config.yml"), 'r') as ff:
        config_version = yaml.safe_load(ff.read()).get(
            "jupyter_book_version"
        )

    if config_version is None:
        raise _error(
            "Couldn't find the version for your Jupyter Book.\n"
            f"Try upgrading it with `jupyter-book upgrade {path_book}"
        )

    if _minor_release(config_version) != _minor_release(__version__):
        raise _error(
            f"The version of the book you are modifying doesn't match the\n"
            "version of the command-line tool that you're using. Please run\n"