"""Allow notebooks to import custom modules at a few pre-defined places within this project's
git repository.

When imported, adds ``GITROOT``, ``GITROOT/src``, and ``GITROOT/notebooks`` to `sys.path`.

Place this file in the same directory as your ``.ipynb`` files. If ``.ipynb`` files are organized
into subfolders, please ensure this file is presented in each subfolder. Example:

.. code-block:: bash

    GITROOT
    |-- .git                   # Signify this is a git repository
    |-- notebooks              # Parent folder of Jupyter notebooks
    |   |-- folder-a
    |   |   |-- my_nb_path.py  # Importable by nb-abc.ipynb and nb-xyz.ipynb
    |   |   |-- nb-abc.ipynb
    |   |   `-- nb-xyz.ipynb
    |   |-- my_nb_path.py      # Importable by nb-01.ipynb and nb-02.ipynb
    |   |-- nb-01.ipynb
    |   `-- nb-02.ipynb
    `-- src
        `-- my_custom_module
            |-- __init__.py
            `-- ...

Usage by ``.ipynb``:

    >>> # Allow this notebook to import from GITROOT, GITROOT/src, and GITROOT/notebooks.
    >>> # This module must be imported before importing any other custom modules under GITROOT.
    >>> # The isort directive prevents the statement to be moved around when isort is used.
    >>> import my_nb_path  # isort: skip
    >>>
    >>> # Test-drive importing a custom module under GITROOT/src.
    >>> import my_custom_module

Background: we used to rely on ``ipython_config.py`` in the current working directory. However,
IPython 8.0.1+, 7.31.1+ and 5.11+ disable this behavior for security reason as described
[here](https://ipython.readthedocs.io/en/stable/whatsnew/version8.html#ipython-8-0-1-cve-2022-21699).

So now, each ``.ipynb`` must explicitly modify its own `sys.path` which is what this module offers
as convenience.
"""
import os
import subprocess  # nosec: B404
import sys
from pathlib import Path
from typing import Union


def sys_path_append(o: Union[str, os.PathLike]) -> None:
    posix_path: str = o.as_posix() if isinstance(o, Path) else Path(o).as_posix()
    if posix_path not in sys.path:
        sys.path.insert(0, posix_path)


try:
    # Add GIT_ROOT/ and a few other subdirs
    _p = subprocess.run(  # nosec: B603 B607
        ["git", "rev-parse", "--show-toplevel"],
        stdout=subprocess.PIPE,
        stderr=subprocess.STDOUT,
    )

    if _p.returncode == 0:
        _git_root: str = _p.stdout[:-1].decode("utf-8")  # Remove trailing '\n'
        _git_root_p = Path(_git_root)

        my_sys_paths = [
            _git_root_p,
            _git_root_p / "src",
            _git_root_p / "notebooks",
        ]
        for sp in my_sys_paths:
            sys_path_append(sp)
except Exception:  # nosec: B110
    # Not a proper git: no CLI, not a git repo, ...
    # So, don't do anything to sys.path
    pass