diff --git a/README.md b/README.md index 032c5f1..1d9c630 100644 --- a/README.md +++ b/README.md @@ -28,6 +28,13 @@ Install: ![pyversions](https://img.shields.io/pypi/pyversions/nbproject) pip install nbproject ``` +Also consider installing `ipylab` for interactive features +if you use `nbpoject` on `jupyter lab` + +``` +pip install ipylab +``` + Get started: ``` diff --git a/nbproject/__init__.py b/nbproject/__init__.py index 53cbc8c..c494549 100644 --- a/nbproject/__init__.py +++ b/nbproject/__init__.py @@ -25,6 +25,15 @@ """ __version__ = "0.10.2" +from .dev._jupyter_lab_commands import _init_frontend + +# init jupyter lab frontend immediately on import +# nothing happens if this is not jupyter lab +try: + _init_frontend() +except: # noqa: E722 + pass + from . import dev from ._header import header from ._meta import meta diff --git a/nbproject/_header.py b/nbproject/_header.py index 55d95a7..b186c0a 100644 --- a/nbproject/_header.py +++ b/nbproject/_header.py @@ -6,6 +6,7 @@ from .dev._frontend_commands import _reload_notebook, _save_notebook from .dev._initialize import initialize_metadata from .dev._jupyter_communicate import notebook_path +from .dev._jupyter_lab_commands import _ipylab_is_installed from .dev._metadata_display import display_html, table_metadata from .dev._notebook import Notebook, read_notebook, write_notebook @@ -17,7 +18,7 @@ msg_init_complete = ( "Init complete. Hit save & reload from disk, i.e, *discard* editor content. If you" " do not want to lose editor changes, hit save *before* running `header()`." - " Consider using Jupyter Lab for a seamless interactive experience." + " Consider using Jupyter Lab with ipylab installed for a seamless interactive experience." ) msg_inconsistent_parent = ( @@ -113,9 +114,13 @@ def header( global _time_run, _filepath, _env _time_run, _filepath, _env = time_run, filepath, env + interactive_envs = ["notebook"] + if _ipylab_is_installed(): + interactive_envs.append("lab") + # initialize if "nbproject" not in nb.metadata: - if env in ("lab", "notebook"): + if env in interactive_envs: _save_notebook(env) nb = read_notebook(filepath) # type: ignore @@ -129,7 +134,7 @@ def header( _output_table(nb, table_metadata(metadata, nb, time_run)) write_notebook(nb, filepath) # type: ignore - if env in ("lab", "notebook"): + if env in interactive_envs: _reload_notebook(env) else: raise SystemExit(msg_init_complete) diff --git a/nbproject/_publish.py b/nbproject/_publish.py index 1a73f10..104d948 100644 --- a/nbproject/_publish.py +++ b/nbproject/_publish.py @@ -5,6 +5,7 @@ from .dev._check_last_cell import check_last_cell from .dev._consecutiveness import check_consecutiveness from .dev._frontend_commands import _save_notebook +from .dev._jupyter_lab_commands import _ipylab_is_installed from .dev._notebook import read_notebook from .dev._set_version import set_version @@ -13,7 +14,7 @@ def run_checks_for_publish( *, calling_statement: str, i_confirm_i_saved: bool = False, **kwargs ): """Runs all checks for publishing.""" - if meta.env in ("lab", "notebook"): + if meta.env == "notebook" or (meta.env == "lab" and _ipylab_is_installed()): _save_notebook(meta.env) else: pretend_no_test_env = ( @@ -26,8 +27,8 @@ def run_checks_for_publish( elif not i_confirm_i_saved: raise RuntimeError( "Make sure you save the notebook in your editor before publishing!\n" - "You can avoid the need for manually saving in Jupyter Lab or Notebook," - " which auto-save the buffer during publish." + "You can avoid the need for manually saving in Jupyter Lab with ipylab installed" + " or Notebook, which auto-save the buffer during publish." ) notebook_title = meta.live.title diff --git a/nbproject/dev/_jupyter_communicate.py b/nbproject/dev/_jupyter_communicate.py index bbd75e4..eab463c 100644 --- a/nbproject/dev/_jupyter_communicate.py +++ b/nbproject/dev/_jupyter_communicate.py @@ -7,7 +7,7 @@ from nbproject._logger import logger -from ._jupyter_lab_commands import _lab_notebook_path +from ._jupyter_lab_commands import _ipylab_is_installed, _lab_notebook_path DIR_KEYS = ("notebook_dir", "root_dir") @@ -153,9 +153,6 @@ def notebook_path(return_env=False): nb_path = PurePath(os.environ["JPY_SESSION_NAME"]) return (nb_path, "lab" if env is None else env) if return_env else nb_path - if server_exception is not None: - raise server_exception - # no running servers if servers_nbapp == [] and servers_juserv == []: logger.warning("Can not find any servers running.") @@ -163,4 +160,12 @@ def notebook_path(return_env=False): logger.warning( "Can not find the notebook in any server session or by using other methods." ) + if not _ipylab_is_installed(): + logger.warning( + "Consider installing ipylab (pip install ipylab) if you use jupyter lab." + ) + + if server_exception is not None: + raise server_exception + return None diff --git a/nbproject/dev/_jupyter_lab_commands.py b/nbproject/dev/_jupyter_lab_commands.py index 8ceb796..70f5abb 100644 --- a/nbproject/dev/_jupyter_lab_commands.py +++ b/nbproject/dev/_jupyter_lab_commands.py @@ -6,32 +6,30 @@ app = None +# called in __init__.py def _init_frontend(): - from ipylab import JupyterFrontEnd + try: + from ipylab import JupyterFrontEnd - global app - if app is None and is_run_from_ipython: - app = JupyterFrontEnd() + global app + if app is None and is_run_from_ipython: + app = JupyterFrontEnd() + except ImportError: + pass def _save_notebook(): - _init_frontend() - if app is not None: app.commands.execute("docmanager:save") sleep(1) def _reload_notebook(): - _init_frontend() - if app is not None: app.commands.execute("docmanager:reload") def _lab_notebook_path(): - _init_frontend() - if app is None: return None @@ -43,3 +41,14 @@ def _lab_notebook_path(): nb_path = None return nb_path + + +def _ipylab_is_installed(): + if app is not None: + return True + try: + import ipylab + + return True + except ImportError: + return False diff --git a/nbproject/dev/_metadata_display.py b/nbproject/dev/_metadata_display.py index 2741514..37347f7 100644 --- a/nbproject/dev/_metadata_display.py +++ b/nbproject/dev/_metadata_display.py @@ -4,6 +4,8 @@ from pydantic import BaseModel +from nbproject._logger import logger + from ._consecutiveness import check_consecutiveness from ._lamin_communicate import lamin_user_settings from ._notebook import Notebook @@ -147,8 +149,9 @@ def table_metadata( if dm.parent() is not None: table.append(["parent", dm.parent()]) - if version != "0": - consecutiveness = check_consecutiveness(notebook) + if version not in {"0", "1"}: + with logger.mute(): + consecutiveness = check_consecutiveness(notebook) table.append(["consecutive_cells", str(consecutiveness)]) dep_store = dm.pypackage() diff --git a/pyproject.toml b/pyproject.toml index 3dbd4e2..4e26ef7 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -21,7 +21,7 @@ dependencies = [ "orjson", "importlib-metadata", "stdlib_list; python_version < '3.10'", - "lamin_utils>=0.5.0", + "lamin_utils>=0.13.2", ] [project.urls]