jupyter-builder 0.1.0a2__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,13 @@
1
+ # Copyright (c) Jupyter Development Team.
2
+ # Distributed under the terms of the Modified BSD License.
3
+
4
+ try:
5
+ from ._version import __version__
6
+ except ImportError:
7
+ # Fallback when using the package in dev mode without installing
8
+ # in editable mode with pip. It is highly recommended to install
9
+ # the package from a stable release or in editable mode: https://pip.pypa.io/en/stable/topics/local-project-installs/#editable-installs
10
+ import warnings
11
+
12
+ warnings.warn("Importing 'jupyter_builder' outside a proper installation.")
13
+ __version__ = "dev"
@@ -0,0 +1,65 @@
1
+ """Jupyter LabExtension Entry Points."""
2
+
3
+ # Copyright (c) Jupyter Development Team.
4
+ # Distributed under the terms of the Modified BSD License.
5
+
6
+ from __future__ import annotations
7
+ import os
8
+ from copy import copy
9
+
10
+ from jupyter_core.application import JupyterApp, base_aliases, base_flags
11
+ from jupyter_core.paths import jupyter_path
12
+ from traitlets import List, Unicode, default
13
+
14
+ from .debug_log_file_mixin import DebugLogFileMixin
15
+
16
+ HERE = os.path.dirname(os.path.abspath(__file__))
17
+
18
+
19
+ # from .federated_labextensions import build_labextension, develop_labextension_py, watch_labextension
20
+
21
+ flags = dict(base_flags)
22
+
23
+ develop_flags = copy(flags)
24
+ develop_flags["overwrite"] = (
25
+ {"DevelopLabExtensionApp": {"overwrite": True}},
26
+ "Overwrite files",
27
+ )
28
+
29
+ aliases = dict(base_aliases)
30
+ aliases["debug-log-path"] = "DebugLogFileMixin.debug_log_path"
31
+
32
+ # VERSION = get_app_version()
33
+ VERSION = 1
34
+
35
+
36
+ class BaseExtensionApp(JupyterApp, DebugLogFileMixin):
37
+ version = VERSION
38
+ flags = flags
39
+ aliases = aliases
40
+ name = "lab"
41
+
42
+ labextensions_path = List(
43
+ Unicode(),
44
+ help="The standard paths to look in for prebuilt JupyterLab extensions",
45
+ )
46
+
47
+ # @default("labextensions_path")
48
+ # def _default_labextensions_path(self):
49
+ # lab = LabApp()
50
+ # lab.load_config_file()
51
+ # return lab.extra_labextensions_path + lab.labextensions_path
52
+ @default("labextensions_path")
53
+ def _default_labextensions_path(self) -> list[str]:
54
+ return jupyter_path("labextensions")
55
+
56
+ def start(self):
57
+ with self.debug_logging():
58
+ self.run_task()
59
+
60
+ def run_task(self):
61
+ pass
62
+
63
+ def _log_format_default(self):
64
+ """A default format for messages"""
65
+ return "%(message)s"
@@ -0,0 +1,115 @@
1
+ """JupyterLab command handler"""
2
+
3
+ # Copyright (c) Jupyter Development Team.
4
+ # Distributed under the terms of the Modified BSD License.
5
+
6
+ import itertools
7
+
8
+ from .jupyterlab_semver import Range, gt, gte, lt, lte
9
+
10
+
11
+ def _test_overlap(spec1, spec2, drop_prerelease1=False, drop_prerelease2=False):
12
+ """Test whether two version specs overlap.
13
+
14
+ Returns `None` if we cannot determine compatibility,
15
+ otherwise whether there is an overlap
16
+ """
17
+ cmp = _compare_ranges(
18
+ spec1, spec2, drop_prerelease1=drop_prerelease1, drop_prerelease2=drop_prerelease2
19
+ )
20
+ if cmp is None:
21
+ return
22
+ return cmp == 0
23
+
24
+
25
+ def _compare_ranges(spec1, spec2, drop_prerelease1=False, drop_prerelease2=False): # noqa
26
+ """Test whether two version specs overlap.
27
+
28
+ Returns `None` if we cannot determine compatibility,
29
+ otherwise return 0 if there is an overlap, 1 if
30
+ spec1 is lower/older than spec2, and -1 if spec1
31
+ is higher/newer than spec2.
32
+ """
33
+ # Test for overlapping semver ranges.
34
+ r1 = Range(spec1, True)
35
+ r2 = Range(spec2, True)
36
+
37
+ # If either range is empty, we cannot verify.
38
+ if not r1.range or not r2.range:
39
+ return
40
+
41
+ # Set return_value to a sentinel value
42
+ return_value = False
43
+
44
+ # r1.set may be a list of ranges if the range involved an ||, so we need to test for overlaps between each pair.
45
+ for r1set, r2set in itertools.product(r1.set, r2.set):
46
+ x1 = r1set[0].semver
47
+ x2 = r1set[-1].semver
48
+ y1 = r2set[0].semver
49
+ y2 = r2set[-1].semver
50
+
51
+ if x1.prerelease and drop_prerelease1:
52
+ x1 = x1.inc("patch")
53
+
54
+ if y1.prerelease and drop_prerelease2:
55
+ y1 = y1.inc("patch")
56
+
57
+ o1 = r1set[0].operator
58
+ o2 = r2set[0].operator
59
+
60
+ # We do not handle (<) specifiers.
61
+ if o1.startswith("<") or o2.startswith("<"):
62
+ continue
63
+
64
+ # Handle single value specifiers.
65
+ lx = lte if x1 == x2 else lt
66
+ ly = lte if y1 == y2 else lt
67
+ gx = gte if x1 == x2 else gt
68
+ gy = gte if x1 == x2 else gt
69
+
70
+ # Handle unbounded (>) specifiers.
71
+ def noop(x, y, z):
72
+ return True
73
+
74
+ if x1 == x2 and o1.startswith(">"):
75
+ lx = noop
76
+ if y1 == y2 and o2.startswith(">"):
77
+ ly = noop
78
+
79
+ # Check for overlap.
80
+ if (
81
+ gte(x1, y1, True)
82
+ and ly(x1, y2, True)
83
+ or gy(x2, y1, True)
84
+ and ly(x2, y2, True)
85
+ or gte(y1, x1, True)
86
+ and lx(y1, x2, True)
87
+ or gx(y2, x1, True)
88
+ and lx(y2, x2, True)
89
+ ):
90
+ # if we ever find an overlap, we can return immediately
91
+ return 0
92
+
93
+ if gte(y1, x2, True):
94
+ if return_value is False:
95
+ # We can possibly return 1
96
+ return_value = 1
97
+ elif return_value == -1:
98
+ # conflicting information, so we must return None
99
+ return_value = None
100
+ continue
101
+
102
+ if gte(x1, y2, True):
103
+ if return_value is False:
104
+ return_value = -1
105
+ elif return_value == 1:
106
+ # conflicting information, so we must return None
107
+ return_value = None
108
+ continue
109
+
110
+ msg = "Unexpected case comparing version ranges"
111
+ raise AssertionError(msg)
112
+
113
+ if return_value is False:
114
+ return_value = None
115
+ return return_value
@@ -0,0 +1,10 @@
1
+ # Copyright (c) Jupyter Development Team.
2
+ # Distributed under the terms of the Modified BSD License.
3
+
4
+ from pathlib import Path
5
+
6
+
7
+ def default_core_path() -> str:
8
+ import jupyterlab
9
+
10
+ return str(Path(jupyterlab.__file__).parent / "staging")
@@ -0,0 +1,64 @@
1
+ # Copyright (c) Jupyter Development Team.
2
+ # Distributed under the terms of the Modified BSD License.
3
+
4
+ import contextlib
5
+ import logging
6
+ import os
7
+ import sys
8
+ import tempfile
9
+ import traceback
10
+ import warnings
11
+
12
+ from traitlets import Unicode
13
+ from traitlets.config import Configurable
14
+
15
+
16
+ class DebugLogFileMixin(Configurable):
17
+ debug_log_path = Unicode("", config=True, help="Path to use for the debug log file")
18
+
19
+ @contextlib.contextmanager
20
+ def debug_logging(self):
21
+ log_path = self.debug_log_path
22
+ if os.path.isdir(log_path):
23
+ log_path = os.path.join(log_path, "jupyterlab-debug.log")
24
+ if not log_path:
25
+ handle, log_path = tempfile.mkstemp(prefix="jupyterlab-debug-", suffix=".log")
26
+ os.close(handle)
27
+ log = self.log
28
+
29
+ # Transfer current log level to the handlers:
30
+ for h in log.handlers:
31
+ h.setLevel(self.log_level)
32
+ log.setLevel("DEBUG")
33
+
34
+ # Create our debug-level file handler:
35
+ _debug_handler = logging.FileHandler(log_path, "w", "utf8", delay=True)
36
+ _log_formatter = self._log_formatter_cls(fmt=self.log_format, datefmt=self.log_datefmt)
37
+ _debug_handler.setFormatter(_log_formatter)
38
+ _debug_handler.setLevel("DEBUG")
39
+
40
+ log.addHandler(_debug_handler)
41
+
42
+ try:
43
+ yield
44
+ except Exception as ex:
45
+ _, _, exc_traceback = sys.exc_info()
46
+ msg = traceback.format_exception(ex.__class__, ex, exc_traceback)
47
+ for line in msg:
48
+ self.log.debug(line)
49
+ if isinstance(ex, SystemExit):
50
+ warnings.warn(f"An error occurred. See the log file for details: {log_path}")
51
+ raise
52
+ warnings.warn("An error occurred.")
53
+ warnings.warn(msg[-1].strip())
54
+ warnings.warn(f"See the log file for details: {log_path}")
55
+ self.exit(1)
56
+ else:
57
+ log.removeHandler(_debug_handler)
58
+ _debug_handler.flush()
59
+ _debug_handler.close()
60
+ try:
61
+ os.remove(log_path)
62
+ except FileNotFoundError:
63
+ pass
64
+ log.removeHandler(_debug_handler)
@@ -0,0 +1,2 @@
1
+ # Copyright (c) Jupyter Development Team.
2
+ # Distributed under the terms of the Modified BSD License.
@@ -0,0 +1,56 @@
1
+ # Copyright (c) Jupyter Development Team.
2
+ # Distributed under the terms of the Modified BSD License.
3
+
4
+ import os
5
+
6
+ from traitlets import Bool, Unicode
7
+
8
+ from ..base_extension_app import BaseExtensionApp
9
+ from ..core_path import default_core_path
10
+ from ..federated_extensions import build_labextension
11
+
12
+ HERE = os.path.dirname(os.path.abspath(__file__))
13
+
14
+
15
+ class BuildLabExtensionApp(BaseExtensionApp):
16
+ description = "(developer) Build labextension"
17
+
18
+ static_url = Unicode("", config=True, help="Sets the url for static assets when building")
19
+
20
+ development = Bool(False, config=True, help="Build in development mode")
21
+
22
+ source_map = Bool(False, config=True, help="Generate source maps")
23
+
24
+ core_path = Unicode(
25
+ default_core_path(),
26
+ config=True,
27
+ help="Directory containing core application package.json file",
28
+ )
29
+
30
+ aliases = {
31
+ "static-url": "BuildLabExtensionApp.static_url",
32
+ "development": "BuildLabExtensionApp.development",
33
+ "source-map": "BuildLabExtensionApp.source_map",
34
+ "core-path": "BuildLabExtensionApp.core_path",
35
+ }
36
+
37
+ def run_task(self):
38
+ self.extra_args = self.extra_args or [os.getcwd()]
39
+ build_labextension(
40
+ self.extra_args[0],
41
+ logger=self.log,
42
+ development=self.development,
43
+ static_url=self.static_url or None,
44
+ source_map=self.source_map,
45
+ core_path=self.core_path or None,
46
+ )
47
+
48
+
49
+ def main():
50
+ app = BuildLabExtensionApp()
51
+ app.initialize()
52
+ app.start()
53
+
54
+
55
+ if __name__ == "__main__":
56
+ main()
@@ -0,0 +1,58 @@
1
+ # Copyright (c) Jupyter Development Team.
2
+ # Distributed under the terms of the Modified BSD License.
3
+
4
+ import os
5
+ from copy import copy
6
+
7
+ from jupyter_core.application import base_flags
8
+ from traitlets import Bool, Unicode
9
+
10
+ from ..base_extension_app import BaseExtensionApp
11
+ from ..federated_extensions import develop_labextension_py
12
+
13
+ flags = dict(base_flags)
14
+ develop_flags = copy(flags)
15
+ develop_flags["overwrite"] = (
16
+ {"DevelopLabExtensionApp": {"overwrite": True}},
17
+ "Overwrite files",
18
+ )
19
+
20
+
21
+ class DevelopLabExtensionApp(BaseExtensionApp):
22
+ description = "(developer) Develop labextension"
23
+
24
+ flags = develop_flags
25
+ user = Bool(False, config=True, help="Whether to do a user install")
26
+ sys_prefix = Bool(True, config=True, help="Use the sys.prefix as the prefix")
27
+ overwrite = Bool(False, config=True, help="Whether to overwrite files") # flags
28
+ symlink = Bool(True, config=False, help="Whether to use a symlink")
29
+
30
+ labextensions_dir = Unicode(
31
+ "",
32
+ config=True,
33
+ help="Full path to labextensions dir (probably use prefix or user)",
34
+ )
35
+
36
+ def run_task(self):
37
+ """Add config for this labextension"""
38
+ self.extra_args = self.extra_args or [os.getcwd()]
39
+ for arg in self.extra_args:
40
+ develop_labextension_py(
41
+ arg,
42
+ user=self.user,
43
+ sys_prefix=self.sys_prefix,
44
+ labextensions_dir=self.labextensions_dir,
45
+ logger=self.log,
46
+ overwrite=self.overwrite,
47
+ symlink=self.symlink,
48
+ )
49
+
50
+
51
+ def main():
52
+ app = DevelopLabExtensionApp()
53
+ app.initialize()
54
+ app.start()
55
+
56
+
57
+ if __name__ == "__main__":
58
+ main()
@@ -0,0 +1,54 @@
1
+ # Copyright (c) Jupyter Development Team.
2
+ # Distributed under the terms of the Modified BSD License.
3
+
4
+ import os
5
+
6
+ from traitlets import Bool, Unicode
7
+
8
+ from ..base_extension_app import BaseExtensionApp
9
+ from ..federated_extensions import watch_labextension
10
+ from ..core_path import default_core_path
11
+
12
+ HERE = os.path.dirname(os.path.abspath(__file__))
13
+
14
+
15
+ class WatchLabExtensionApp(BaseExtensionApp):
16
+ description = "(developer) Watch labextension"
17
+
18
+ development = Bool(True, config=True, help="Build in development mode")
19
+
20
+ source_map = Bool(False, config=True, help="Generate source maps")
21
+
22
+ core_path = Unicode(
23
+ default_core_path(),
24
+ config=True,
25
+ help="Directory containing core application package.json file",
26
+ )
27
+
28
+ aliases = {
29
+ "core-path": "WatchLabExtensionApp.core_path",
30
+ "development": "WatchLabExtensionApp.development",
31
+ "source-map": "WatchLabExtensionApp.source_map",
32
+ }
33
+
34
+ def run_task(self):
35
+ self.extra_args = self.extra_args or [os.getcwd()]
36
+ labextensions_path = self.labextensions_path
37
+ watch_labextension(
38
+ self.extra_args[0],
39
+ labextensions_path,
40
+ logger=self.log,
41
+ development=self.development,
42
+ source_map=self.source_map,
43
+ core_path=self.core_path or None,
44
+ )
45
+
46
+
47
+ def main():
48
+ app = WatchLabExtensionApp()
49
+ app.initialize()
50
+ app.start()
51
+
52
+
53
+ if __name__ == "__main__":
54
+ main()