File size: 4,753 Bytes
d1ceb73
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
"""JupyterLab Server Application"""

# Copyright (c) Jupyter Development Team.
# Distributed under the terms of the Modified BSD License.

from glob import glob
from os.path import relpath
from typing import Any

from jupyter_server.extension.application import ExtensionApp, ExtensionAppJinjaMixin
from jupyter_server.utils import url_path_join as ujoin
from traitlets import Dict, Integer, Unicode, observe

from ._version import __version__
from .handlers import LabConfig, add_handlers


class LabServerApp(ExtensionAppJinjaMixin, LabConfig, ExtensionApp):
    """A Lab Server Application that runs out-of-the-box"""

    name = "jupyterlab_server"
    extension_url = "/lab"
    app_name = "JupyterLab Server Application"  # type:ignore[assignment]
    file_url_prefix = "/lab/tree"  # type:ignore[assignment]

    @property
    def app_namespace(self) -> str:  # type:ignore[override]
        return self.name

    default_url = Unicode("/lab", help="The default URL to redirect to from `/`")

    # Should your extension expose other server extensions when launched directly?
    load_other_extensions = True

    app_version = Unicode("", help="The version of the application.").tag(default=__version__)

    blacklist_uris = Unicode(
        "", config=True, help="Deprecated, use `LabServerApp.blocked_extensions_uris`"
    )

    blocked_extensions_uris = Unicode(
        "",
        config=True,
        help="""
        A list of comma-separated URIs to get the blocked extensions list

        .. versionchanged:: 2.0.0
            `LabServerApp.blacklist_uris` renamed to `blocked_extensions_uris`
        """,
    )

    whitelist_uris = Unicode(
        "", config=True, help="Deprecated, use `LabServerApp.allowed_extensions_uris`"
    )

    allowed_extensions_uris = Unicode(
        "",
        config=True,
        help="""
        "A list of comma-separated URIs to get the allowed extensions list

        .. versionchanged:: 2.0.0
            `LabServerApp.whitetlist_uris` renamed to `allowed_extensions_uris`
        """,
    )

    listings_refresh_seconds = Integer(
        60 * 60, config=True, help="The interval delay in seconds to refresh the lists"
    )

    listings_request_options = Dict(
        {},
        config=True,
        help="The optional kwargs to use for the listings HTTP requests \
            as described on https://2.python-requests.org/en/v2.7.0/api/#requests.request",
    )

    _deprecated_aliases = {
        "blacklist_uris": ("blocked_extensions_uris", "1.2"),
        "whitelist_uris": ("allowed_extensions_uris", "1.2"),
    }

    # Method copied from
    # https://github.com/jupyterhub/jupyterhub/blob/d1a85e53dccfc7b1dd81b0c1985d158cc6b61820/jupyterhub/auth.py#L143-L161
    @observe(*list(_deprecated_aliases))
    def _deprecated_trait(self, change: Any) -> None:
        """observer for deprecated traits"""
        old_attr = change.name
        new_attr, version = self._deprecated_aliases.get(old_attr)  # type:ignore[misc]
        new_value = getattr(self, new_attr)
        if new_value != change.new:
            # only warn if different
            # protects backward-compatible config from warnings
            # if they set the same value under both names
            self.log.warning(
                "%s.%s is deprecated in JupyterLab %s, use %s.%s instead",
                self.__class__.__name__,
                old_attr,
                version,
                self.__class__.__name__,
                new_attr,
            )

            setattr(self, new_attr, change.new)

    def initialize_settings(self) -> None:
        """Initialize the settings:

        set the static files as immutable, since they should have all hashed name.
        """
        immutable_cache = set(self.settings.get("static_immutable_cache", []))

        # Set lab static files as immutables
        immutable_cache.add(self.static_url_prefix)

        # Set extensions static files as immutables
        for extension_path in self.labextensions_path + self.extra_labextensions_path:
            extensions_url = [
                ujoin(self.labextensions_url, relpath(path, extension_path))
                for path in glob(f"{extension_path}/**/static", recursive=True)
            ]

            immutable_cache.update(extensions_url)

        self.settings.update({"static_immutable_cache": list(immutable_cache)})

    def initialize_templates(self) -> None:
        """Initialize templates."""
        self.static_paths = [self.static_dir]
        self.template_paths = [self.templates_dir]

    def initialize_handlers(self) -> None:
        """Initialize handlers."""
        add_handlers(self.handlers, self)


main = launch_new_instance = LabServerApp.launch_instance