Skip to content

Commit

Permalink
Merge pull request jupyterlab#145 from jupyterlab/fcollonval-patch-1
Browse files Browse the repository at this point in the history
Update server extension entry points
  • Loading branch information
jtpio authored Feb 16, 2021
2 parents ca71190 + dcea63b commit 9d0a3c1
Show file tree
Hide file tree
Showing 6 changed files with 137 additions and 110 deletions.
128 changes: 67 additions & 61 deletions advanced/server-extension/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -331,51 +331,51 @@ your extension needs to be defined as a proper Python package with some hook fun
# jlab_ext_example/__init__.py

import json
import os.path as osp
from pathlib import Path

from .handlers import setup_handlers
from ._version import __version__

HERE = osp.abspath(osp.dirname(__file__))
HERE = Path(__file__).parent.resolve()

with open(osp.join(HERE, 'labextension', 'package.json')) as fid:
with (HERE / "labextension" / "package.json").open() as fid:
data = json.load(fid)


def _jupyter_labextension_paths():
return [{
'src': 'labextension',
'dest': data['name']
}]
return [{"src": "labextension", "dest": data["name"]}]


def _jupyter_server_extension_paths():
def _jupyter_server_extension_points():
return [{"module": "jlab_ext_example"}]


def load_jupyter_server_extension(lab_app):
def _load_jupyter_server_extension(server_app):
"""Registers the API handler to receive HTTP requests from the frontend extension.
Parameters
----------
lab_app: jupyterlab.labapp.LabApp
server_app: jupyterlab.labapp.LabApp
JupyterLab application instance
"""
url_path = "jlab-ext-example"
setup_handlers(lab_app.web_app, url_path)
lab_app.log.info(
"Registered jlab_ext_example extension at URL path /{}".format(url_path)
setup_handlers(server_app.web_app, url_path)
server_app.log.info(
f"Registered jlab_ext_example extension at URL path /{url_path}"
)

# For backward compatibility with the classical notebook
load_jupyter_server_extension = _load_jupyter_server_extension

```
The `_jupyter_server_extension_paths` provides the Python package name
to the server. But the most important one is `load_jupyter_server_extension`
The `_jupyter_server_extension_points` provides the Python package name
to the server. But the most important one is `_load_jupyter_server_extension`
that register new handlers.
```py
# jlab_ext_example/__init__.py#L31-L31
# jlab_ext_example/__init__.py#L29-L29

setup_handlers(lab_app.web_app, url_path)
setup_handlers(server_app.web_app, url_path)
```
A handler is registered in the web application by linking an url to a class. In this
Expand Down Expand Up @@ -496,81 +496,77 @@ The `setup.py` file is the entry point to describe package metadata:
jlab_ext_example setup
"""
import json
import os
from pathlib import Path

from jupyter_packaging import (
create_cmdclass, install_npm, ensure_targets,
combine_commands, skip_if_exists
create_cmdclass,
install_npm,
ensure_targets,
combine_commands,
skip_if_exists,
)
import setuptools

HERE = os.path.abspath(os.path.dirname(__file__))
HERE = Path(__file__).parent.resolve()

# The name of the project
name="jlab_ext_example"

# Get our version
with open(os.path.join(HERE, 'package.json')) as f:
version = json.load(f)['version']
name = "jlab_ext_example"

lab_path = os.path.join(HERE, name, "labextension")
lab_path = HERE / name / "labextension"

# Representative files that should exist after a successful build
jstargets = [
os.path.join(lab_path, "package.json"),
str(lab_path / "package.json"),
]

package_data_spec = {
name: [
"*"
]
}
package_data_spec = {name: ["*"]}

labext_name = "@jupyterlab-examples/server-extension"

data_files_spec = [
("share/jupyter/labextensions/%s" % labext_name, lab_path, "**"),
("share/jupyter/labextensions/%s" % labext_name, HERE, "install.json"),("etc/jupyter/jupyter_server_config.d",
"jupyter-config", "jlab_ext_example.json"),

("share/jupyter/labextensions/%s" % labext_name, str(lab_path), "**"),
("share/jupyter/labextensions/%s" % labext_name, str(HERE), "install.json"),
("etc/jupyter/jupyter_notebook_config.d", "jupyter-config/jupyter_notebook_config.d", "jlab_ext_example.json"),
("etc/jupyter/jupyter_server_config.d", "jupyter-config/jupyter_server_config.d", "jlab_ext_example.json"),
]

cmdclass = create_cmdclass("jsdeps",
package_data_spec=package_data_spec,
data_files_spec=data_files_spec
cmdclass = create_cmdclass(
"jsdeps", package_data_spec=package_data_spec, data_files_spec=data_files_spec
)

js_command = combine_commands(
install_npm(HERE, build_cmd="build:prod", npm=["jlpm"]),
ensure_targets(jstargets),
)

is_repo = os.path.exists(os.path.join(HERE, ".git"))
is_repo = (HERE / ".git").exists()
if is_repo:
cmdclass["jsdeps"] = js_command
else:
cmdclass["jsdeps"] = skip_if_exists(jstargets, js_command)

with open("README.md", "r") as fh:
long_description = fh.read()
long_description = (HERE / "README.md").read_text()

# Get the package info from package.json
pkg_json = json.loads((HERE / "package.json").read_bytes())

setup_args = dict(
name=name,
version=version,
url="https://github.com/jupyterlab/extension-examples.git",
author="Project Jupyter Contributors",
description="A minimal JupyterLab extension with backend and frontend parts.",
long_description= long_description,
version=pkg_json["version"],
url=pkg_json["homepage"],
author=pkg_json["author"],
description=pkg_json["description"],
license=pkg_json["license"],
long_description=long_description,
long_description_content_type="text/markdown",
cmdclass= cmdclass,
cmdclass=cmdclass,
packages=setuptools.find_packages(),
install_requires=[
"jupyterlab>=3.0.0rc15,==3.*",
"jupyterlab~=3.0",
],
zip_safe=False,
include_package_data=True,
python_requires=">=3.6",
license="BSD-3-Clause",
platforms="Linux, Mac OS X, Windows",
keywords=["Jupyter", "JupyterLab", "JupyterLab3"],
classifiers=[
Expand All @@ -580,6 +576,7 @@ setup_args = dict(
"Programming Language :: Python :: 3.6",
"Programming Language :: Python :: 3.7",
"Programming Language :: Python :: 3.8",
"Programming Language :: Python :: 3.9",
"Framework :: Jupyter",
],
)
Expand All @@ -596,11 +593,10 @@ the frontend NPM package needs to be built and inserted in the Python package. T
done using a special `cmdclass`:
```py
# setup.py#L44-L52
# setup.py#L39-L46

cmdclass = create_cmdclass("jsdeps",
package_data_spec=package_data_spec,
data_files_spec=data_files_spec
cmdclass = create_cmdclass(
"jsdeps", package_data_spec=package_data_spec, data_files_spec=data_files_spec
)

js_command = combine_commands(
Expand All @@ -612,28 +608,29 @@ js_command = combine_commands(
Basically it will build the frontend NPM package:
```py
# setup.py#L50-L50
# setup.py#L44-L44

install_npm(HERE, build_cmd="build:prod", npm=["jlpm"]),
```
It will ensure one of the generated files is `jlab_ext_example/labextension/package.json`:
```py
# setup.py#L24-L27
# setup.py#L23-L26

# Representative files that should exist after a successful build
jstargets = [
os.path.join(lab_path, "package.json"),
str(lab_path / "package.json"),
]
```
It will copy the NPM package in the Python package and force it to be copied in a place
JupyterLab is looking for frontend extensions when the Python package is installed:
```py
# setup.py#L33-L33

("share/jupyter/labextensions/%s" % labext_name, lab_path, "*.*")
("share/jupyter/labextensions/%s" % labext_name, str(lab_path), "**"),
```
The last piece of configuration needed is the enabling of the server extension. This is
Expand All @@ -655,9 +652,18 @@ done by copying the following JSON file:
in the appropriate jupyter folder (`etc/jupyter/jupyter_server_config.d`):
```py
# setup.py#L36-L36

("etc/jupyter/jupyter_server_config.d", "jupyter-config/jupyter_server_config.d", "jlab_ext_example.json"),
```
For backward compatibility with the classical notebook, the old version of that file is copied in
(`etc/jupyter/jupyter_notebook_config.d`):
```py
# setup.py#L35-L35

("etc/jupyter/jupyter_server_config.d",
"jupyter-config", "jlab_ext_example.json"),
("etc/jupyter/jupyter_notebook_config.d", "jupyter-config/jupyter_notebook_config.d", "jlab_ext_example.json"),
```
### JupyterLab Extension Manager
Expand Down
27 changes: 14 additions & 13 deletions advanced/server-extension/jlab_ext_example/__init__.py
Original file line number Diff line number Diff line change
@@ -1,34 +1,35 @@
import json
import os.path as osp
from pathlib import Path

from .handlers import setup_handlers
from ._version import __version__

HERE = osp.abspath(osp.dirname(__file__))
HERE = Path(__file__).parent.resolve()

with open(osp.join(HERE, 'labextension', 'package.json')) as fid:
with (HERE / "labextension" / "package.json").open() as fid:
data = json.load(fid)


def _jupyter_labextension_paths():
return [{
'src': 'labextension',
'dest': data['name']
}]
return [{"src": "labextension", "dest": data["name"]}]


def _jupyter_server_extension_paths():
def _jupyter_server_extension_points():
return [{"module": "jlab_ext_example"}]


def load_jupyter_server_extension(lab_app):
def _load_jupyter_server_extension(server_app):
"""Registers the API handler to receive HTTP requests from the frontend extension.
Parameters
----------
lab_app: jupyterlab.labapp.LabApp
server_app: jupyterlab.labapp.LabApp
JupyterLab application instance
"""
url_path = "jlab-ext-example"
setup_handlers(lab_app.web_app, url_path)
lab_app.log.info(
"Registered jlab_ext_example extension at URL path /{}".format(url_path)
setup_handlers(server_app.web_app, url_path)
server_app.log.info(
f"Registered jlab_ext_example extension at URL path /{url_path}"
)

# For backward compatibility with the classical notebook
load_jupyter_server_extension = _load_jupyter_server_extension
20 changes: 18 additions & 2 deletions advanced/server-extension/jlab_ext_example/_version.py
Original file line number Diff line number Diff line change
@@ -1,2 +1,18 @@
version_info = (0, 1, 0)
__version__ = ".".join(map(str, version_info))
import json
from pathlib import Path

__all__ = ["__version__"]

def _fetchVersion():
HERE = Path(__file__).parent.resolve()

for settings in HERE.rglob("package.json"):
try:
with settings.open() as f:
return json.load(f)["version"]
except FileNotFoundError:
pass

raise FileNotFoundError(f"Could not find package.json under dir {HERE!s}")

__version__ = _fetchVersion()
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"NotebookApp": {
"nbserver_extensions": {
"jlab_ext_example": true
}
}
}
Loading

0 comments on commit 9d0a3c1

Please sign in to comment.