1# coding: utf-8 2# Copyright (c) Jupyter Development Team. 3# Distributed under the terms of the Modified BSD License. 4 5import json 6import os.path as osp 7from itertools import filterfalse 8 9from .jlpmapp import HERE 10 11 12def pjoin(*args): 13 """Join paths to create a real path. 14 """ 15 return osp.abspath(osp.join(*args)) 16 17 18def _get_default_core_data(): 19 """Get the data for the app template. 20 """ 21 with open(pjoin(HERE, 'staging', 'package.json')) as fid: 22 return json.load(fid) 23 24 25def _is_lab_package(name): 26 """Whether a package name is in the lab namespace""" 27 return name.startswith('@jupyterlab/') 28 29 30def _only_nonlab(collection): 31 """Filter a dict/sequence to remove all lab packages 32 33 This is useful to take the default values of e.g. singletons and filter 34 away the '@jupyterlab/' namespace packages, but leave any others (e.g. 35 lumino and react). 36 """ 37 if isinstance(collection, dict): 38 return dict( 39 (k, v) for (k, v) in collection.items() 40 if not _is_lab_package(k) 41 ) 42 elif isinstance(collection, (list, tuple)): 43 return list(filterfalse(_is_lab_package, collection)) 44 raise TypeError('collection arg should be either dict or list/tuple') 45 46 47class CoreConfig: 48 """An object representing a core config. 49 50 This enables custom lab application to override some parts of the core 51 configuration of the build system. 52 """ 53 def __init__(self): 54 self._data = _get_default_core_data() 55 56 def add(self, name, semver, extension=False, mime_extension=False): 57 """Remove an extension/singleton. 58 59 If neither extension or mimeExtension is True (the default) 60 the package is added as a singleton dependency. 61 62 name: string 63 The npm package name 64 semver: string 65 The semver range for the package 66 extension: bool 67 Whether the package is an extension 68 mime_extension: bool 69 Whether the package is a MIME extension 70 """ 71 data = self._data 72 if not name: 73 raise ValueError('Missing package name') 74 if not semver: 75 raise ValueError('Missing package semver') 76 if name in data['resolutions']: 77 raise ValueError('Package already present: %r' % (name,)) 78 data['resolutions'][name] = semver 79 80 # If both mimeExtension and extensions are True, treat 81 # as mime extension 82 if mime_extension: 83 data['jupyterlab']['mimeExtensions'][name] = "" 84 data['dependencies'][name] = semver 85 elif extension: 86 data['jupyterlab']['extensions'][name] = "" 87 data['dependencies'][name] = semver 88 else: 89 data['jupyterlab']['singletonPackages'].append(name) 90 91 def remove(self, name): 92 """Remove a package/extension. 93 94 name: string 95 The npm package name 96 """ 97 data = self._data 98 maps = ( 99 data['dependencies'], 100 data['resolutions'], 101 data['jupyterlab']['extensions'], 102 data['jupyterlab']['mimeExtensions'], 103 ) 104 for m in maps: 105 try: 106 del m[name] 107 except KeyError: 108 pass 109 110 data['jupyterlab']['singletonPackages'].remove(name) 111 112 def clear_packages(self, lab_only=True): 113 """Clear the packages/extensions. 114 """ 115 data = self._data 116 # Clear all dependencies 117 if lab_only: 118 # Clear all "@jupyterlab/" dependencies 119 data['dependencies'] = _only_nonlab(data['dependencies']) 120 data['resolutions'] = _only_nonlab(data['resolutions']) 121 data['jupyterlab']['extensions'] = _only_nonlab( 122 data['jupyterlab']['extensions']) 123 data['jupyterlab']['mimeExtensions'] = _only_nonlab( 124 data['jupyterlab']['mimeExtensions']) 125 data['jupyterlab']['singletonPackages'] = _only_nonlab( 126 data['jupyterlab']['singletonPackages']) 127 else: 128 data['dependencies'] = {} 129 data['resolutions'] = {} 130 data['jupyterlab']['extensions'] = {} 131 data['jupyterlab']['mimeExtensions'] = {} 132 data['jupyterlab']['singletonPackages'] = [] 133 134 @property 135 def extensions(self): 136 """A dict mapping all extension names to their semver""" 137 data = self._data 138 return dict( 139 (k, data['resolutions'][k]) 140 for k in data['jupyterlab']['extensions'].keys()) 141 142 @property 143 def mime_extensions(self): 144 """A dict mapping all MIME extension names to their semver""" 145 data = self._data 146 return dict( 147 (k, data['resolutions'][k]) 148 for k in data['jupyterlab']['mimeExtensions'].keys()) 149 150 @property 151 def singletons(self): 152 """A dict mapping all singleton names to their semver""" 153 data = self._data 154 return dict( 155 (k, data['resolutions'].get(k, None)) 156 for k in data['jupyterlab']['singletonPackages']) 157 158 @property 159 def static_dir(self): 160 return self._data['jupyterlab']['staticDir'] 161 162 @static_dir.setter 163 def static_dir(self, static_dir): 164 self._data['jupyterlab']['staticDir'] = static_dir 165