Skip to content

Commit 9d0a3c1

Browse files
authored
Merge pull request #145 from jupyterlab/fcollonval-patch-1
Update server extension entry points
2 parents ca71190 + dcea63b commit 9d0a3c1

File tree

6 files changed

+137
-110
lines changed

6 files changed

+137
-110
lines changed

advanced/server-extension/README.md

Lines changed: 67 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -331,51 +331,51 @@ your extension needs to be defined as a proper Python package with some hook fun
331331
# jlab_ext_example/__init__.py
332332

333333
import json
334-
import os.path as osp
334+
from pathlib import Path
335335

336336
from .handlers import setup_handlers
337337
from ._version import __version__
338338

339-
HERE = osp.abspath(osp.dirname(__file__))
339+
HERE = Path(__file__).parent.resolve()
340340

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

344+
344345
def _jupyter_labextension_paths():
345-
return [{
346-
'src': 'labextension',
347-
'dest': data['name']
348-
}]
346+
return [{"src": "labextension", "dest": data["name"]}]
349347

350348

351-
def _jupyter_server_extension_paths():
349+
def _jupyter_server_extension_points():
352350
return [{"module": "jlab_ext_example"}]
353351

354352

355-
def load_jupyter_server_extension(lab_app):
353+
def _load_jupyter_server_extension(server_app):
356354
"""Registers the API handler to receive HTTP requests from the frontend extension.
357355
Parameters
358356
----------
359-
lab_app: jupyterlab.labapp.LabApp
357+
server_app: jupyterlab.labapp.LabApp
360358
JupyterLab application instance
361359
"""
362360
url_path = "jlab-ext-example"
363-
setup_handlers(lab_app.web_app, url_path)
364-
lab_app.log.info(
365-
"Registered jlab_ext_example extension at URL path /{}".format(url_path)
361+
setup_handlers(server_app.web_app, url_path)
362+
server_app.log.info(
363+
f"Registered jlab_ext_example extension at URL path /{url_path}"
366364
)
367365

366+
# For backward compatibility with the classical notebook
367+
load_jupyter_server_extension = _load_jupyter_server_extension
368368

369369
```
370370
371-
The `_jupyter_server_extension_paths` provides the Python package name
372-
to the server. But the most important one is `load_jupyter_server_extension`
371+
The `_jupyter_server_extension_points` provides the Python package name
372+
to the server. But the most important one is `_load_jupyter_server_extension`
373373
that register new handlers.
374374
375375
```py
376-
# jlab_ext_example/__init__.py#L31-L31
376+
# jlab_ext_example/__init__.py#L29-L29
377377

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

501501
from jupyter_packaging import (
502-
create_cmdclass, install_npm, ensure_targets,
503-
combine_commands, skip_if_exists
502+
create_cmdclass,
503+
install_npm,
504+
ensure_targets,
505+
combine_commands,
506+
skip_if_exists,
504507
)
505508
import setuptools
506509

507-
HERE = os.path.abspath(os.path.dirname(__file__))
510+
HERE = Path(__file__).parent.resolve()
508511

509512
# The name of the project
510-
name="jlab_ext_example"
511-
512-
# Get our version
513-
with open(os.path.join(HERE, 'package.json')) as f:
514-
version = json.load(f)['version']
513+
name = "jlab_ext_example"
515514

516-
lab_path = os.path.join(HERE, name, "labextension")
515+
lab_path = HERE / name / "labextension"
517516

518517
# Representative files that should exist after a successful build
519518
jstargets = [
520-
os.path.join(lab_path, "package.json"),
519+
str(lab_path / "package.json"),
521520
]
522521

523-
package_data_spec = {
524-
name: [
525-
"*"
526-
]
527-
}
522+
package_data_spec = {name: ["*"]}
528523

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

531526
data_files_spec = [
532-
("share/jupyter/labextensions/%s" % labext_name, lab_path, "**"),
533-
("share/jupyter/labextensions/%s" % labext_name, HERE, "install.json"),("etc/jupyter/jupyter_server_config.d",
534-
"jupyter-config", "jlab_ext_example.json"),
535-
527+
("share/jupyter/labextensions/%s" % labext_name, str(lab_path), "**"),
528+
("share/jupyter/labextensions/%s" % labext_name, str(HERE), "install.json"),
529+
("etc/jupyter/jupyter_notebook_config.d", "jupyter-config/jupyter_notebook_config.d", "jlab_ext_example.json"),
530+
("etc/jupyter/jupyter_server_config.d", "jupyter-config/jupyter_server_config.d", "jlab_ext_example.json"),
536531
]
537532

538-
cmdclass = create_cmdclass("jsdeps",
539-
package_data_spec=package_data_spec,
540-
data_files_spec=data_files_spec
533+
cmdclass = create_cmdclass(
534+
"jsdeps", package_data_spec=package_data_spec, data_files_spec=data_files_spec
541535
)
542536

543537
js_command = combine_commands(
544538
install_npm(HERE, build_cmd="build:prod", npm=["jlpm"]),
545539
ensure_targets(jstargets),
546540
)
547541

548-
is_repo = os.path.exists(os.path.join(HERE, ".git"))
542+
is_repo = (HERE / ".git").exists()
549543
if is_repo:
550544
cmdclass["jsdeps"] = js_command
551545
else:
552546
cmdclass["jsdeps"] = skip_if_exists(jstargets, js_command)
553547

554-
with open("README.md", "r") as fh:
555-
long_description = fh.read()
548+
long_description = (HERE / "README.md").read_text()
549+
550+
# Get the package info from package.json
551+
pkg_json = json.loads((HERE / "package.json").read_bytes())
556552

557553
setup_args = dict(
558554
name=name,
559-
version=version,
560-
url="https://github.com/jupyterlab/extension-examples.git",
561-
author="Project Jupyter Contributors",
562-
description="A minimal JupyterLab extension with backend and frontend parts.",
563-
long_description= long_description,
555+
version=pkg_json["version"],
556+
url=pkg_json["homepage"],
557+
author=pkg_json["author"],
558+
description=pkg_json["description"],
559+
license=pkg_json["license"],
560+
long_description=long_description,
564561
long_description_content_type="text/markdown",
565-
cmdclass= cmdclass,
562+
cmdclass=cmdclass,
566563
packages=setuptools.find_packages(),
567564
install_requires=[
568-
"jupyterlab>=3.0.0rc15,==3.*",
565+
"jupyterlab~=3.0",
569566
],
570567
zip_safe=False,
571568
include_package_data=True,
572569
python_requires=">=3.6",
573-
license="BSD-3-Clause",
574570
platforms="Linux, Mac OS X, Windows",
575571
keywords=["Jupyter", "JupyterLab", "JupyterLab3"],
576572
classifiers=[
@@ -580,6 +576,7 @@ setup_args = dict(
580576
"Programming Language :: Python :: 3.6",
581577
"Programming Language :: Python :: 3.7",
582578
"Programming Language :: Python :: 3.8",
579+
"Programming Language :: Python :: 3.9",
583580
"Framework :: Jupyter",
584581
],
585582
)
@@ -596,11 +593,10 @@ the frontend NPM package needs to be built and inserted in the Python package. T
596593
done using a special `cmdclass`:
597594
598595
```py
599-
# setup.py#L44-L52
596+
# setup.py#L39-L46
600597

601-
cmdclass = create_cmdclass("jsdeps",
602-
package_data_spec=package_data_spec,
603-
data_files_spec=data_files_spec
598+
cmdclass = create_cmdclass(
599+
"jsdeps", package_data_spec=package_data_spec, data_files_spec=data_files_spec
604600
)
605601

606602
js_command = combine_commands(
@@ -612,28 +608,29 @@ js_command = combine_commands(
612608
Basically it will build the frontend NPM package:
613609
614610
```py
615-
# setup.py#L50-L50
611+
# setup.py#L44-L44
616612

617613
install_npm(HERE, build_cmd="build:prod", npm=["jlpm"]),
618614
```
619615
620616
It will ensure one of the generated files is `jlab_ext_example/labextension/package.json`:
621617
622618
```py
623-
# setup.py#L24-L27
619+
# setup.py#L23-L26
624620

625621
# Representative files that should exist after a successful build
626622
jstargets = [
627-
os.path.join(lab_path, "package.json"),
623+
str(lab_path / "package.json"),
628624
]
629625
```
630626
631627
It will copy the NPM package in the Python package and force it to be copied in a place
632628
JupyterLab is looking for frontend extensions when the Python package is installed:
633629
634630
```py
631+
# setup.py#L33-L33
635632

636-
("share/jupyter/labextensions/%s" % labext_name, lab_path, "*.*")
633+
("share/jupyter/labextensions/%s" % labext_name, str(lab_path), "**"),
637634
```
638635
639636
The last piece of configuration needed is the enabling of the server extension. This is
@@ -655,9 +652,18 @@ done by copying the following JSON file:
655652
in the appropriate jupyter folder (`etc/jupyter/jupyter_server_config.d`):
656653
657654
```py
655+
# setup.py#L36-L36
656+
657+
("etc/jupyter/jupyter_server_config.d", "jupyter-config/jupyter_server_config.d", "jlab_ext_example.json"),
658+
```
659+
660+
For backward compatibility with the classical notebook, the old version of that file is copied in
661+
(`etc/jupyter/jupyter_notebook_config.d`):
662+
663+
```py
664+
# setup.py#L35-L35
658665

659-
("etc/jupyter/jupyter_server_config.d",
660-
"jupyter-config", "jlab_ext_example.json"),
666+
("etc/jupyter/jupyter_notebook_config.d", "jupyter-config/jupyter_notebook_config.d", "jlab_ext_example.json"),
661667
```
662668
663669
### JupyterLab Extension Manager
Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,35 @@
11
import json
2-
import os.path as osp
2+
from pathlib import Path
33

44
from .handlers import setup_handlers
55
from ._version import __version__
66

7-
HERE = osp.abspath(osp.dirname(__file__))
7+
HERE = Path(__file__).parent.resolve()
88

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

12+
1213
def _jupyter_labextension_paths():
13-
return [{
14-
'src': 'labextension',
15-
'dest': data['name']
16-
}]
14+
return [{"src": "labextension", "dest": data["name"]}]
1715

1816

19-
def _jupyter_server_extension_paths():
17+
def _jupyter_server_extension_points():
2018
return [{"module": "jlab_ext_example"}]
2119

2220

23-
def load_jupyter_server_extension(lab_app):
21+
def _load_jupyter_server_extension(server_app):
2422
"""Registers the API handler to receive HTTP requests from the frontend extension.
2523
Parameters
2624
----------
27-
lab_app: jupyterlab.labapp.LabApp
25+
server_app: jupyterlab.labapp.LabApp
2826
JupyterLab application instance
2927
"""
3028
url_path = "jlab-ext-example"
31-
setup_handlers(lab_app.web_app, url_path)
32-
lab_app.log.info(
33-
"Registered jlab_ext_example extension at URL path /{}".format(url_path)
29+
setup_handlers(server_app.web_app, url_path)
30+
server_app.log.info(
31+
f"Registered jlab_ext_example extension at URL path /{url_path}"
3432
)
33+
34+
# For backward compatibility with the classical notebook
35+
load_jupyter_server_extension = _load_jupyter_server_extension
Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,18 @@
1-
version_info = (0, 1, 0)
2-
__version__ = ".".join(map(str, version_info))
1+
import json
2+
from pathlib import Path
3+
4+
__all__ = ["__version__"]
5+
6+
def _fetchVersion():
7+
HERE = Path(__file__).parent.resolve()
8+
9+
for settings in HERE.rglob("package.json"):
10+
try:
11+
with settings.open() as f:
12+
return json.load(f)["version"]
13+
except FileNotFoundError:
14+
pass
15+
16+
raise FileNotFoundError(f"Could not find package.json under dir {HERE!s}")
17+
18+
__version__ = _fetchVersion()
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
{
2+
"NotebookApp": {
3+
"nbserver_extensions": {
4+
"jlab_ext_example": true
5+
}
6+
}
7+
}

0 commit comments

Comments
 (0)