Skip to content

Commit

Permalink
Tweak and test
Browse files Browse the repository at this point in the history
  • Loading branch information
vidartf committed Aug 14, 2019
1 parent 900b847 commit 853a5f5
Show file tree
Hide file tree
Showing 3 changed files with 115 additions and 72 deletions.
8 changes: 5 additions & 3 deletions jupyterlab/commands.py
Expand Up @@ -29,7 +29,7 @@

from .semver import Range, gte, lt, lte, gt, make_semver
from .jlpmapp import YARN_PATH, HERE
from .coreconfig import CoreConfig
from .coreconfig import _get_default_core_data


# The regex for expecting the webpack output.
Expand Down Expand Up @@ -483,7 +483,9 @@ def __init__(self, app_dir, logger=None, kill_event=None, core_config=None):
self.app_dir = app_dir or get_app_dir()
self.sys_dir = get_app_dir()
self.logger = _ensure_logger(logger)
self.core_data = (core_config or CoreConfig()).data
self.core_data = (
core_config._data if core_config else _get_default_core_data()
)
self.info = self._get_app_info()
self.kill_event = kill_event or Event()
# TODO: Make this configurable
Expand Down Expand Up @@ -1629,7 +1631,7 @@ def _node_check(logger):
output = subprocess.check_output([node, 'node-version-check.js'], cwd=HERE)
logger.debug(output.decode('utf-8'))
except Exception:
data = CoreConfig().data
data = CoreConfig()._data
ver = data['engines']['node']
msg = 'Please install nodejs %s before continuing. nodejs may be installed using conda or directly from the nodejs website.' % ver
raise ValueError(msg)
Expand Down
129 changes: 62 additions & 67 deletions jupyterlab/coreconfig.py
Expand Up @@ -2,6 +2,7 @@
# Copyright (c) Jupyter Development Team.
# Distributed under the terms of the Modified BSD License.

from collections import defaultdict
from itertools import filterfalse
import json
import os.path as osp
Expand All @@ -15,7 +16,7 @@ def pjoin(*args):
return osp.abspath(osp.join(*args))


def _get_core_data():
def _get_default_core_data():
"""Get the data for the app template.
"""
with open(pjoin(HERE, 'staging', 'package.json')) as fid:
Expand All @@ -28,7 +29,12 @@ def _is_lab_package(name):


def _only_nonlab(collection):
"""Filter a dict/sequence to remove all lab packages"""
"""Filter a dict/sequence to remove all lab packages
This is useful to take the default values of e.g. singletons and filter
away the '@jupyterlab/' namespace packages, but leave any others (e.g.
phosphor and react).
"""
if isinstance(collection, dict):
return dict(
(k, v) for (k, v) in collection.items()
Expand All @@ -40,43 +46,13 @@ def _only_nonlab(collection):


class CoreConfig:
"""An object representing a core-mode package/extension configuration.
"""An object representing a core config.
This enables custom lab application to change the core configuration
of the various build system commands. See e.g. commands.py and
any apps that use these functions.
This enables custom lab application to override some parts of the core
configuration of the build system.
"""

def __init__(self):
self._data = _get_core_data()

def clear_defaults(self, lab_only=True):
"""Clear the default packages/extensions.
lab_only: bool
Whether to remove all packages, or only those from
JupyterLab. Defaults to True (only lab packages).
This will leave dependencies like phosphor, react
etc untouched.
"""
data = self._data
if lab_only:
# Clear all "@jupyterlab/" dependencies
data['dependencies'] = _only_nonlab(data['dependencies'])
data['resolutions'] = _only_nonlab(data['resolutions'])
data['jupyterlab']['extensions'] = _only_nonlab(
data['jupyterlab']['extensions'])
data['jupyterlab']['mimeExtensions'] = _only_nonlab(
data['jupyterlab']['mimeExtensions'])
data['jupyterlab']['singletonPackages'] = _only_nonlab(
data['jupyterlab']['singletonPackages'])
else:
# Clear all dependencies
data['dependencies'] = {}
data['resolutions'] = {}
data['jupyterlab']['extensions'] = {}
data['jupyterlab']['mimeExtensions'] = {}
data['jupyterlab']['singletonPackages'] = []
self._data = _get_default_core_data()

def add(self, name, semver, extension=False, mime_extension=False):
"""Remove an extension/singleton.
Expand All @@ -98,7 +74,7 @@ def add(self, name, semver, extension=False, mime_extension=False):
raise ValueError('Missing package name')
if not semver:
raise ValueError('Missing package semver')
if name in self._data['resolutions']:
if name in data['resolutions']:
raise ValueError('Package already present: %r' % (name,))
data['resolutions'][name] = semver

Expand All @@ -113,28 +89,6 @@ def add(self, name, semver, extension=False, mime_extension=False):
else:
data['jupyterlab']['singletonPackages'].append(name)

@property
def extensions(self):
"""A dict mapping all extension names to their semver"""
return dict(
(k, self._data['resolutions'][k])
for k in self._data['jupyterlab']['extensions'].keys())

@property
def mime_extensions(self):
"""A dict mapping all MIME extension names to their semver"""
return dict(
(k, self._data['resolutions'][k])
for k in self._data['jupyterlab']['mimeExtensions'].keys())

@property
def singletons(self):
"""A dict mapping all singleton names to their semver"""
return dict(
(k, self._data['resolutions'][k])
for k in self._data['jupyterlab']['singletonPackages']
)

def remove(self, name):
"""Remove a package/extension.
Expand All @@ -156,15 +110,56 @@ def remove(self, name):

data['jupyterlab']['singletonPackages'].remove(name)

def clear_packages(self, lab_only=True):
"""Clear the packages/extensions.
"""
data = self._data
# Clear all dependencies
if lab_only:
# Clear all "@jupyterlab/" dependencies
data['dependencies'] = _only_nonlab(data['dependencies'])
data['resolutions'] = _only_nonlab(data['resolutions'])
data['jupyterlab']['extensions'] = _only_nonlab(
data['jupyterlab']['extensions'])
data['jupyterlab']['mimeExtensions'] = _only_nonlab(
data['jupyterlab']['mimeExtensions'])
data['jupyterlab']['singletonPackages'] = _only_nonlab(
data['jupyterlab']['singletonPackages'])
else:
data['dependencies'] = {}
data['resolutions'] = {}
data['jupyterlab']['extensions'] = {}
data['jupyterlab']['mimeExtensions'] = {}
data['jupyterlab']['singletonPackages'] = []

def set_static_dir(self, static_dir):
self._data['jupyterlab']['staticDir'] = static_dir
@property
def extensions(self):
"""A dict mapping all extension names to their semver"""
data = self._data
return dict(
(k, data['resolutions'][k])
for k in data['jupyterlab']['extensions'].keys())

@property
def data(self):
"""Returns the raw core data.
def mime_extensions(self):
"""A dict mapping all MIME extension names to their semver"""
data = self._data
return dict(
(k, data['resolutions'][k])
for k in data['jupyterlab']['mimeExtensions'].keys())

Its content should be considered an internal implementation
detail of lab, and should not be relied upon outide of lab.
"""
return self._data
@property
def singletons(self):
"""A dict mapping all singleton names to their semver"""
data = self._data
return dict(
(k, data['resolutions'].get(k, None))
for k in data['jupyterlab']['singletonPackages'])

@property
def static_dir(self):
return self._data['jupyterlab']['staticDir']

@static_dir.setter
def static_dir(self, static_dir):
self._data['jupyterlab']['staticDir'] = static_dir
50 changes: 48 additions & 2 deletions jupyterlab/tests/test_jupyterlab.py
Expand Up @@ -5,6 +5,7 @@
# Distributed under the terms of the Modified BSD License.
import glob
import json
import logging
import os
import shutil
import sys
Expand All @@ -25,7 +26,7 @@
disable_extension, enable_extension, get_app_info,
check_extension, _test_overlap, update_extension
)
from jupyterlab.coreconfig import CoreConfig
from jupyterlab.coreconfig import CoreConfig, _get_default_core_data

here = os.path.dirname(os.path.abspath(__file__))

Expand Down Expand Up @@ -379,6 +380,51 @@ def test_build_custom(self):
assert data['jupyterlab']['version'] == '1.0'
assert data['jupyterlab']['staticUrl'] == 'bar'

def test_build_custom_minimal_core_config(self):
default_config = CoreConfig()
core_config = CoreConfig()
core_config.clear_packages()
logger = logging.getLogger('jupyterlab_test_logger')
logger.setLevel('DEBUG')
extensions = (
'@jupyterlab/application-extension',
'@jupyterlab/apputils-extension',
)
singletons = (
"@jupyterlab/application",
"@jupyterlab/apputils",
"@jupyterlab/coreutils",
"@jupyterlab/services",
)
for name in extensions:
semver = default_config.extensions[name]
core_config.add(name, semver, extension=True)
for name in singletons:
semver = default_config.singletons[name]
core_config.add(name, semver)

assert install_extension(self.mock_extension) is True
build(core_config=core_config, logger=logger)

# check static directory.
entry = pjoin(self.app_dir, 'static', 'index.out.js')
with open(entry) as fid:
data = fid.read()
assert self.pkg_names['extension'] in data

pkg = pjoin(self.app_dir, 'static', 'package.json')
with open(pkg) as fid:
data = json.load(fid)
assert list(data['jupyterlab']['extensions'].keys()) == [
'@jupyterlab/application-extension',
'@jupyterlab/apputils-extension',
self.pkg_names['extension'],
]
assert data['jupyterlab']['mimeExtensions'] == {}
for pkg in data['jupyterlab']['singletonPackages']:
if pkg.startswith('@jupyterlab/'):
assert pkg in singletons

def test_load_extension(self):
app = NotebookApp()
stderr = sys.stderr
Expand Down Expand Up @@ -477,7 +523,7 @@ def test_compatibility(self):
assert _test_overlap('<0.6', '0.1') is None

def test_install_compatible(self):
core_data = CoreConfig().data
core_data = _get_default_core_data()
current_app_dep = core_data['dependencies']['@jupyterlab/application']
def _gen_dep(ver):
return { "dependencies": {
Expand Down

0 comments on commit 853a5f5

Please sign in to comment.