jupyter-builder 0.1.0a2__py3-none-any.whl → 0.1.0a4__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.
- jupyter_builder/__init__.py +1 -1
- jupyter_builder/base_extension_app.py +1 -3
- jupyter_builder/commands.py +6 -9
- jupyter_builder/debug_log_file_mixin.py +7 -7
- jupyter_builder/extension_commands/build.py +4 -4
- jupyter_builder/extension_commands/develop.py +2 -2
- jupyter_builder/extension_commands/watch.py +4 -4
- jupyter_builder/federated_extensions.py +36 -43
- jupyter_builder/federated_extensions_requirements.py +12 -12
- jupyter_builder/jupyterlab_semver.py +970 -3
- jupyter_builder/yarn.js +8 -13
- jupyter_builder-0.1.0a4.dist-info/METADATA +175 -0
- jupyter_builder-0.1.0a4.dist-info/RECORD +20 -0
- {jupyter_builder-0.1.0a2.dist-info → jupyter_builder-0.1.0a4.dist-info}/WHEEL +1 -1
- jupyter_builder/jupyterlab_server_req.py +0 -66
- jupyter_builder-0.1.0a2.dist-info/METADATA +0 -119
- jupyter_builder-0.1.0a2.dist-info/RECORD +0 -21
- {jupyter_builder-0.1.0a2.dist-info → jupyter_builder-0.1.0a4.dist-info}/entry_points.txt +0 -0
- {jupyter_builder-0.1.0a2.dist-info → jupyter_builder-0.1.0a4.dist-info}/licenses/LICENSE +0 -0
jupyter_builder/__init__.py
CHANGED
|
@@ -9,5 +9,5 @@ except ImportError:
|
|
|
9
9
|
# the package from a stable release or in editable mode: https://pip.pypa.io/en/stable/topics/local-project-installs/#editable-installs
|
|
10
10
|
import warnings
|
|
11
11
|
|
|
12
|
-
warnings.warn("Importing 'jupyter_builder' outside a proper installation.")
|
|
12
|
+
warnings.warn("Importing 'jupyter_builder' outside a proper installation.", stacklevel=1)
|
|
13
13
|
__version__ = "dev"
|
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
# Distributed under the terms of the Modified BSD License.
|
|
5
5
|
|
|
6
6
|
from __future__ import annotations
|
|
7
|
+
|
|
7
8
|
import os
|
|
8
9
|
from copy import copy
|
|
9
10
|
|
|
@@ -15,9 +16,6 @@ from .debug_log_file_mixin import DebugLogFileMixin
|
|
|
15
16
|
|
|
16
17
|
HERE = os.path.dirname(os.path.abspath(__file__))
|
|
17
18
|
|
|
18
|
-
|
|
19
|
-
# from .federated_labextensions import build_labextension, develop_labextension_py, watch_labextension
|
|
20
|
-
|
|
21
19
|
flags = dict(base_flags)
|
|
22
20
|
|
|
23
21
|
develop_flags = copy(flags)
|
jupyter_builder/commands.py
CHANGED
|
@@ -41,7 +41,8 @@ def _compare_ranges(spec1, spec2, drop_prerelease1=False, drop_prerelease2=False
|
|
|
41
41
|
# Set return_value to a sentinel value
|
|
42
42
|
return_value = False
|
|
43
43
|
|
|
44
|
-
# r1.set may be a list of ranges if the range involved an ||,
|
|
44
|
+
# r1.set may be a list of ranges if the range involved an ||,
|
|
45
|
+
# so we need to test for overlaps between each pair.
|
|
45
46
|
for r1set, r2set in itertools.product(r1.set, r2.set):
|
|
46
47
|
x1 = r1set[0].semver
|
|
47
48
|
x2 = r1set[-1].semver
|
|
@@ -78,14 +79,10 @@ def _compare_ranges(spec1, spec2, drop_prerelease1=False, drop_prerelease2=False
|
|
|
78
79
|
|
|
79
80
|
# Check for overlap.
|
|
80
81
|
if (
|
|
81
|
-
gte(x1, y1, True)
|
|
82
|
-
and ly(
|
|
83
|
-
or
|
|
84
|
-
|
|
85
|
-
or gte(y1, x1, True)
|
|
86
|
-
and lx(y1, x2, True)
|
|
87
|
-
or gx(y2, x1, True)
|
|
88
|
-
and lx(y2, x2, True)
|
|
82
|
+
(gte(x1, y1, True) and ly(x1, y2, True))
|
|
83
|
+
or (gy(x2, y1, True) and ly(x2, y2, True))
|
|
84
|
+
or (gte(y1, x1, True) and lx(y1, x2, True))
|
|
85
|
+
or (gx(y2, x1, True) and lx(y2, x2, True))
|
|
89
86
|
):
|
|
90
87
|
# if we ever find an overlap, we can return immediately
|
|
91
88
|
return 0
|
|
@@ -47,18 +47,18 @@ class DebugLogFileMixin(Configurable):
|
|
|
47
47
|
for line in msg:
|
|
48
48
|
self.log.debug(line)
|
|
49
49
|
if isinstance(ex, SystemExit):
|
|
50
|
-
warnings.warn(
|
|
50
|
+
warnings.warn(
|
|
51
|
+
f"An error occurred. See the log file for details: {log_path}", stacklevel=1
|
|
52
|
+
)
|
|
51
53
|
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}")
|
|
54
|
+
warnings.warn("An error occurred.", stacklevel=1)
|
|
55
|
+
warnings.warn(msg[-1].strip(), stacklevel=1)
|
|
56
|
+
warnings.warn(f"See the log file for details: {log_path}", stacklevel=1)
|
|
55
57
|
self.exit(1)
|
|
56
58
|
else:
|
|
57
59
|
log.removeHandler(_debug_handler)
|
|
58
60
|
_debug_handler.flush()
|
|
59
61
|
_debug_handler.close()
|
|
60
|
-
|
|
62
|
+
with contextlib.suppress(FileNotFoundError):
|
|
61
63
|
os.remove(log_path)
|
|
62
|
-
except FileNotFoundError:
|
|
63
|
-
pass
|
|
64
64
|
log.removeHandler(_debug_handler)
|
|
@@ -5,9 +5,9 @@ import os
|
|
|
5
5
|
|
|
6
6
|
from traitlets import Bool, Unicode
|
|
7
7
|
|
|
8
|
-
from
|
|
9
|
-
from
|
|
10
|
-
from
|
|
8
|
+
from jupyter_builder.base_extension_app import BaseExtensionApp
|
|
9
|
+
from jupyter_builder.core_path import default_core_path
|
|
10
|
+
from jupyter_builder.federated_extensions import build_labextension
|
|
11
11
|
|
|
12
12
|
HERE = os.path.dirname(os.path.abspath(__file__))
|
|
13
13
|
|
|
@@ -27,7 +27,7 @@ class BuildLabExtensionApp(BaseExtensionApp):
|
|
|
27
27
|
help="Directory containing core application package.json file",
|
|
28
28
|
)
|
|
29
29
|
|
|
30
|
-
aliases = {
|
|
30
|
+
aliases = { # noqa: RUF012
|
|
31
31
|
"static-url": "BuildLabExtensionApp.static_url",
|
|
32
32
|
"development": "BuildLabExtensionApp.development",
|
|
33
33
|
"source-map": "BuildLabExtensionApp.source_map",
|
|
@@ -7,8 +7,8 @@ from copy import copy
|
|
|
7
7
|
from jupyter_core.application import base_flags
|
|
8
8
|
from traitlets import Bool, Unicode
|
|
9
9
|
|
|
10
|
-
from
|
|
11
|
-
from
|
|
10
|
+
from jupyter_builder.base_extension_app import BaseExtensionApp
|
|
11
|
+
from jupyter_builder.federated_extensions import develop_labextension_py
|
|
12
12
|
|
|
13
13
|
flags = dict(base_flags)
|
|
14
14
|
develop_flags = copy(flags)
|
|
@@ -5,9 +5,9 @@ import os
|
|
|
5
5
|
|
|
6
6
|
from traitlets import Bool, Unicode
|
|
7
7
|
|
|
8
|
-
from
|
|
9
|
-
from
|
|
10
|
-
from
|
|
8
|
+
from jupyter_builder.base_extension_app import BaseExtensionApp
|
|
9
|
+
from jupyter_builder.core_path import default_core_path
|
|
10
|
+
from jupyter_builder.federated_extensions import watch_labextension
|
|
11
11
|
|
|
12
12
|
HERE = os.path.dirname(os.path.abspath(__file__))
|
|
13
13
|
|
|
@@ -25,7 +25,7 @@ class WatchLabExtensionApp(BaseExtensionApp):
|
|
|
25
25
|
help="Directory containing core application package.json file",
|
|
26
26
|
)
|
|
27
27
|
|
|
28
|
-
aliases = {
|
|
28
|
+
aliases = { # noqa: RUF012
|
|
29
29
|
"core-path": "WatchLabExtensionApp.core_path",
|
|
30
30
|
"development": "WatchLabExtensionApp.development",
|
|
31
31
|
"source-map": "WatchLabExtensionApp.source_map",
|
|
@@ -25,7 +25,6 @@ from jupyter_core.paths import ENV_JUPYTER_PATH, SYSTEM_JUPYTER_PATH, jupyter_da
|
|
|
25
25
|
from jupyter_core.utils import ensure_dir_exists
|
|
26
26
|
from jupyter_server.extension.serverextension import ArgumentConflict
|
|
27
27
|
|
|
28
|
-
# from jupyterlab_server.config import get_federated_extensions
|
|
29
28
|
from .federated_extensions_requirements import get_federated_extensions
|
|
30
29
|
|
|
31
30
|
try:
|
|
@@ -33,7 +32,8 @@ try:
|
|
|
33
32
|
except ImportError:
|
|
34
33
|
from tomli import load
|
|
35
34
|
|
|
36
|
-
|
|
35
|
+
from .commands import _test_overlap
|
|
36
|
+
from .core_path import default_core_path
|
|
37
37
|
|
|
38
38
|
DEPRECATED_ARGUMENT = object()
|
|
39
39
|
|
|
@@ -95,7 +95,7 @@ def develop_labextension( # noqa
|
|
|
95
95
|
ensure_dir_exists(labext)
|
|
96
96
|
|
|
97
97
|
if isinstance(path, (list, tuple)):
|
|
98
|
-
msg = "path must be a string pointing to a single extension to install; call this function multiple times to install multiple extensions"
|
|
98
|
+
msg = "path must be a string pointing to a single extension to install; call this function multiple times to install multiple extensions" # noqa: E501
|
|
99
99
|
raise TypeError(msg)
|
|
100
100
|
|
|
101
101
|
if not destination:
|
|
@@ -104,7 +104,7 @@ def develop_labextension( # noqa
|
|
|
104
104
|
full_dest = normpath(pjoin(labext, destination))
|
|
105
105
|
if overwrite and os.path.lexists(full_dest):
|
|
106
106
|
if logger:
|
|
107
|
-
logger.info("Removing: %s"
|
|
107
|
+
logger.info("Removing: %s", full_dest)
|
|
108
108
|
if os.path.isdir(full_dest) and not os.path.islink(full_dest):
|
|
109
109
|
shutil.rmtree(full_dest)
|
|
110
110
|
else:
|
|
@@ -124,14 +124,15 @@ def develop_labextension( # noqa
|
|
|
124
124
|
if platform.platform().startswith("Windows"):
|
|
125
125
|
msg = (
|
|
126
126
|
"Symlinks can be activated on Windows 10 for Python version 3.8 or higher"
|
|
127
|
-
" by activating the 'Developer Mode'. That may not be allowed by your administrators.\n"
|
|
127
|
+
" by activating the 'Developer Mode'. That may not be allowed by your administrators.\n" # noqa: E501
|
|
128
128
|
"See https://docs.microsoft.com/en-us/windows/apps/get-started/enable-your-device-for-development"
|
|
129
129
|
)
|
|
130
130
|
raise OSError(msg) from e
|
|
131
131
|
raise
|
|
132
132
|
|
|
133
133
|
elif not os.path.islink(full_dest):
|
|
134
|
-
|
|
134
|
+
msg = f"{full_dest} exists and is not a symlink"
|
|
135
|
+
raise ValueError(msg)
|
|
135
136
|
|
|
136
137
|
elif os.path.isdir(path):
|
|
137
138
|
path = pjoin(os.path.abspath(path), "") # end in path separator
|
|
@@ -139,7 +140,7 @@ def develop_labextension( # noqa
|
|
|
139
140
|
dest_dir = pjoin(full_dest, parent[len(path) :])
|
|
140
141
|
if not os.path.exists(dest_dir):
|
|
141
142
|
if logger:
|
|
142
|
-
logger.info("Making directory: %s"
|
|
143
|
+
logger.info("Making directory: %s", dest_dir)
|
|
143
144
|
os.makedirs(dest_dir)
|
|
144
145
|
for file_name in files:
|
|
145
146
|
src = pjoin(parent, file_name)
|
|
@@ -152,7 +153,7 @@ def develop_labextension( # noqa
|
|
|
152
153
|
return full_dest
|
|
153
154
|
|
|
154
155
|
|
|
155
|
-
def develop_labextension_py(
|
|
156
|
+
def develop_labextension_py( # noqa: PLR0913
|
|
156
157
|
module,
|
|
157
158
|
user=False,
|
|
158
159
|
sys_prefix=False,
|
|
@@ -195,20 +196,15 @@ def develop_labextension_py(
|
|
|
195
196
|
return full_dests
|
|
196
197
|
|
|
197
198
|
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
def build_labextension(
|
|
199
|
+
def build_labextension( # noqa: PLR0913
|
|
202
200
|
path, logger=None, development=False, static_url=None, source_map=False, core_path=None
|
|
203
201
|
):
|
|
204
202
|
"""Build a labextension in the given path"""
|
|
205
|
-
|
|
206
203
|
core_path = default_core_path() if core_path is None else str(Path(core_path).resolve())
|
|
207
|
-
|
|
208
204
|
ext_path = str(Path(path).resolve())
|
|
209
205
|
|
|
210
206
|
if logger:
|
|
211
|
-
logger.info("Building extension in %s"
|
|
207
|
+
logger.info("Building extension in %s", path)
|
|
212
208
|
|
|
213
209
|
builder = _ensure_builder(ext_path, core_path)
|
|
214
210
|
|
|
@@ -223,7 +219,7 @@ def build_labextension(
|
|
|
223
219
|
subprocess.check_call(arguments, cwd=ext_path) # noqa S603
|
|
224
220
|
|
|
225
221
|
|
|
226
|
-
def watch_labextension(
|
|
222
|
+
def watch_labextension( # noqa: PLR0913
|
|
227
223
|
path, labextensions_path, logger=None, development=False, source_map=False, core_path=None
|
|
228
224
|
):
|
|
229
225
|
"""Watch a labextension in a given path"""
|
|
@@ -231,7 +227,7 @@ def watch_labextension(
|
|
|
231
227
|
ext_path = str(Path(path).resolve())
|
|
232
228
|
|
|
233
229
|
if logger:
|
|
234
|
-
logger.info("Building extension in %s"
|
|
230
|
+
logger.info("Building extension in %s", path)
|
|
235
231
|
|
|
236
232
|
# Check to see if we need to create a symlink
|
|
237
233
|
federated_extensions = get_federated_extensions(labextensions_path)
|
|
@@ -274,9 +270,8 @@ def _ensure_builder(ext_path, core_path):
|
|
|
274
270
|
dep_version2 = ext_data.get("devDependencies", {}).get("@jupyterlab/builder")
|
|
275
271
|
dep_version2 = dep_version2 or ext_data.get("dependencies", {}).get("@jupyterlab/builder")
|
|
276
272
|
if dep_version2 is None:
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
)
|
|
273
|
+
msg = f"Extensions require a devDependency on @jupyterlab/builder@{dep_version1}"
|
|
274
|
+
raise ValueError(msg)
|
|
280
275
|
|
|
281
276
|
# if we have installed from disk (version is a path), assume we know what
|
|
282
277
|
# we are doing and do not check versions.
|
|
@@ -295,23 +290,22 @@ def _ensure_builder(ext_path, core_path):
|
|
|
295
290
|
raise ValueError(msg)
|
|
296
291
|
target = osp.dirname(target)
|
|
297
292
|
|
|
298
|
-
#
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
# )
|
|
293
|
+
# Check for compatible versions
|
|
294
|
+
overlap = _test_overlap(
|
|
295
|
+
dep_version1, dep_version2, drop_prerelease1=True, drop_prerelease2=True
|
|
296
|
+
)
|
|
297
|
+
if not overlap:
|
|
298
|
+
with open(
|
|
299
|
+
osp.join(target, "node_modules", "@jupyterlab", "builder", "package.json")
|
|
300
|
+
) as fid:
|
|
301
|
+
dep_version2 = json.load(fid).get("version")
|
|
302
|
+
overlap = _test_overlap(
|
|
303
|
+
dep_version1, dep_version2, drop_prerelease1=True, drop_prerelease2=True
|
|
304
|
+
)
|
|
311
305
|
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
306
|
+
if not overlap:
|
|
307
|
+
msg = f"Extensions require a devDependency on @jupyterlab/builder@{dep_version1}, you have a dependency on {dep_version2}" # noqa: E501
|
|
308
|
+
raise ValueError(msg)
|
|
315
309
|
|
|
316
310
|
return osp.join(
|
|
317
311
|
target, "node_modules", "@jupyterlab", "builder", "lib", "build-labextension.js"
|
|
@@ -339,10 +333,10 @@ def _should_copy(src, dest, logger=None):
|
|
|
339
333
|
# we add a fudge factor to work around a bug in python 2.x
|
|
340
334
|
# that was fixed in python 3.x: https://bugs.python.org/issue12904
|
|
341
335
|
if logger:
|
|
342
|
-
logger.warning("Out of date: %s"
|
|
336
|
+
logger.warning("Out of date: %s", dest)
|
|
343
337
|
return True
|
|
344
338
|
if logger:
|
|
345
|
-
logger.info("Up to date: %s"
|
|
339
|
+
logger.info("Up to date: %s", dest)
|
|
346
340
|
return False
|
|
347
341
|
|
|
348
342
|
|
|
@@ -388,9 +382,8 @@ def _get_labextension_dir(user=False, sys_prefix=False, prefix=None, labextensio
|
|
|
388
382
|
]
|
|
389
383
|
conflicting_set = [f"{n}={v!r}" for n, v in conflicting if v]
|
|
390
384
|
if len(conflicting_set) > 1:
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
)
|
|
385
|
+
conflict = ", ".join(conflicting_set)
|
|
386
|
+
msg = f"cannot specify more than one of user, sys_prefix, prefix, or labextensions_dir, but got: {conflict}" # noqa: E501
|
|
394
387
|
raise ArgumentConflict(msg)
|
|
395
388
|
if user:
|
|
396
389
|
labext = pjoin(jupyter_data_dir(), "labextensions")
|
|
@@ -449,8 +442,8 @@ def _get_labextension_metadata(module): # noqa
|
|
|
449
442
|
if not package:
|
|
450
443
|
try:
|
|
451
444
|
package = (
|
|
452
|
-
subprocess.check_output(
|
|
453
|
-
[sys.executable, "setup.py", "--name"],
|
|
445
|
+
subprocess.check_output( # noqa: S603
|
|
446
|
+
[sys.executable, "setup.py", "--name"],
|
|
454
447
|
cwd=mod_path,
|
|
455
448
|
)
|
|
456
449
|
.decode("utf8")
|
|
@@ -50,21 +50,21 @@ def get_federated_extensions(labextensions_path: list[str]) -> dict[str, Any]:
|
|
|
50
50
|
with open(ext_path, encoding="utf-8") as fid:
|
|
51
51
|
pkgdata = json.load(fid)
|
|
52
52
|
if pkgdata["name"] not in federated_extensions:
|
|
53
|
-
data =
|
|
54
|
-
name
|
|
55
|
-
version
|
|
56
|
-
description
|
|
57
|
-
url
|
|
58
|
-
ext_dir
|
|
59
|
-
ext_path
|
|
60
|
-
is_local
|
|
61
|
-
dependencies
|
|
62
|
-
jupyterlab
|
|
63
|
-
|
|
53
|
+
data = {
|
|
54
|
+
"name": pkgdata["name"],
|
|
55
|
+
"version": pkgdata["version"],
|
|
56
|
+
"description": pkgdata.get("description", ""),
|
|
57
|
+
"url": get_package_url(pkgdata),
|
|
58
|
+
"ext_dir": ext_dir,
|
|
59
|
+
"ext_path": osp.dirname(ext_path),
|
|
60
|
+
"is_local": False,
|
|
61
|
+
"dependencies": pkgdata.get("dependencies", {}),
|
|
62
|
+
"jupyterlab": pkgdata.get("jupyterlab", {}),
|
|
63
|
+
}
|
|
64
64
|
|
|
65
65
|
# Add repository info if available
|
|
66
66
|
if "repository" in pkgdata and "url" in pkgdata.get("repository", {}):
|
|
67
|
-
data["repository"] =
|
|
67
|
+
data["repository"] = {"url": pkgdata.get("repository").get("url")}
|
|
68
68
|
|
|
69
69
|
install_path = osp.join(osp.dirname(ext_path), "install.json")
|
|
70
70
|
if osp.exists(install_path):
|