1- """Install RobotKernel wheels."""
2- from importlib import resources
1+ """Install RobotKernel wheels.
2+
3+ Update wheels.json for RobotKernelAddon:
4+
5+ python -m jupyterlite_robotkernel.addons.robotkernel
6+
7+ """
8+ from typing import List
9+
310from jupyterlite .addons .base import BaseAddon
11+ from jupyterlite .addons .piplite import PIPLITE_URLS
12+ from jupyterlite .addons .piplite import PYPI_WHEELS
13+ from jupyterlite .constants import ALL_JSON
14+ from jupyterlite .constants import JSON_FMT
415from jupyterlite .constants import JUPYTERLITE_JSON
5- from jupyterlite .constants import LITE_PLUGIN_SETTINGS
616from jupyterlite .constants import JUPYTER_CONFIG_DATA
17+ from jupyterlite .constants import LITE_PLUGIN_SETTINGS
718from jupyterlite .constants import UTF8
8- from jupyterlite .constants import ALL_JSON
9- from jupyterlite .constants import JSON_FMT
10- from jupyterlite .addons .piplite import PYPI_WHEELS
11- from jupyterlite .addons .piplite import PIPLITE_URLS
12- from pathlib import Path
19+
20+ from contextlib import contextmanager
1321from hashlib import sha256
22+ from importlib import resources
23+ from pathlib import Path
24+ from tempfile import mkdtemp
1425
26+ import argparse
1527import json
28+ import os
29+ import shutil
30+ import subprocess
31+ import sys
1632import traitlets
1733
34+ PY = Path (sys .executable )
1835DEFAULT_WHEELS = json .loads (
1936 resources .read_text ("jupyterlite_robotkernel.addons" , "wheels.json" )
2037)
@@ -28,6 +45,11 @@ class RobotKernelAddon(BaseAddon):
2845
2946 wheel_urls = traitlets .List (DEFAULT_WHEELS ).tag (config = True )
3047
48+ def __init__ (self , manager , * args , ** kwargs ):
49+ kwargs ["parent" ] = manager
50+ kwargs ["manager" ] = manager
51+ super ().__init__ (* args , ** kwargs )
52+
3153 def pre_build (self , manager ):
3254 """Downloads wheels."""
3355 for wheel in self .wheel_urls :
@@ -95,3 +117,68 @@ def get_index_urls(self, whl_index):
95117 whl_index_url = f"./{ whl_index .relative_to (self .manager .output_dir ).as_posix ()} "
96118 whl_index_url_with_sha = f"{ whl_index_url } ?sha256={ whl_index_sha256 } "
97119 return whl_index_url , whl_index_url_with_sha
120+
121+
122+ @contextmanager
123+ def NamedTemporaryDirectory ():
124+ tmpdir = mkdtemp ()
125+ try :
126+ yield tmpdir
127+ finally :
128+ shutil .rmtree (tmpdir )
129+
130+
131+ def resolve_wheel_urls (reqs : List [str ]) -> List [str ]:
132+ with NamedTemporaryDirectory () as tmpdir :
133+ return _resolve_wheel_urls (tmpdir , reqs )
134+
135+
136+ def _resolve_wheel_urls (tmpdir : str , reqs : List [str ]) -> List [str ]:
137+ cwd = Path (tmpdir ).resolve ()
138+ cwd .mkdir (parents = True , exist_ok = True )
139+ # Install robotkernel
140+ subprocess .check_call ([PY , "-m" , "pip" , "wheel" , "--prefer-binary" , * reqs ], cwd = cwd )
141+ # Remove wheels that conflict with pyolite shims
142+ for path in cwd .glob ("ipykernel-*" ):
143+ os .unlink (path )
144+ for path in cwd .glob ("widgetsnbextension-*" ):
145+ os .unlink (path )
146+ # Remove binary wheels
147+ for path in set (cwd .glob ("*" )) - (set (cwd .glob ("*-none-any.whl" ))):
148+ os .unlink (path )
149+ # Freeze
150+ PY2_PY3_EXCEPTIONS = ["testpath-0.6.0-py3-none-any.whl" ]
151+ return [
152+ f"""https://files.pythonhosted.org/packages/py2.py3/{ path .name [0 ]} /{ path .name .split ("-" )[0 ]} /{ path .name } """
153+ for path in sorted (cwd .glob ("*-none-any.whl" ))
154+ if path .name .endswith ("py2.py3-none-any.whl" ) or path .name in PY2_PY3_EXCEPTIONS
155+ ] + [
156+ f"""https://files.pythonhosted.org/packages/py3/{ path .name [0 ]} /{ path .name .split ("-" )[0 ]} /{ path .name } """
157+ for path in sorted (cwd .glob ("*-none-any.whl" ))
158+ if not path .name .endswith ("py2.py3-none-any.whl" )
159+ and path .name not in PY2_PY3_EXCEPTIONS
160+ ]
161+
162+
163+ if __name__ == "__main__" :
164+ parser = argparse .ArgumentParser (
165+ description = "Resolve RobotKernel wheel with dependencies."
166+ )
167+ parser .add_argument (
168+ "--inplace" ,
169+ action = argparse .BooleanOptionalAction ,
170+ help = "update RobotKernel wheel_urls `--inplace` or create/update `jupyter_lite_config.json` (default)" ,
171+ )
172+ args = parser .parse_args ()
173+ wheel_urls = resolve_wheel_urls (["robotkernel >=1.6a1" ])
174+ config = Path (os .getcwd ()) / "jupyter_lite_config.json"
175+ if args .inplace :
176+ (Path (__file__ ).parent / "wheels.json" ).write_text (
177+ json .dumps (wheel_urls , indent = 4 )
178+ )
179+ else :
180+ config_json = json .loads (config .read_text ()) if config .exists () else {}
181+ config_json .setdefault ("LiteBuildConfig" , {})
182+ config_json .setdefault ("RobotKernelAddon" , {}).setdefault ("wheel_urls" , [])
183+ config_json ["RobotKernelAddon" ]["wheel_urls" ] = wheel_urls
184+ config .write_text (json .dumps (config_json , indent = 4 ))
0 commit comments