From e39a70265440f07d029314b388451e6339a0e6fe Mon Sep 17 00:00:00 2001 From: Nicholas Bollweg Date: Thu, 10 Mar 2016 11:21:32 -0500 Subject: [PATCH 1/2] documenting public members of nbextension --- notebook/nbextensions.py | 187 +++++++++++++++++++++++++++++++++++---- 1 file changed, 172 insertions(+), 15 deletions(-) diff --git a/notebook/nbextensions.py b/notebook/nbextensions.py index 71977833c..dcb6c10e4 100644 --- a/notebook/nbextensions.py +++ b/notebook/nbextensions.py @@ -72,6 +72,8 @@ def check_nbextension(files, user=False, prefix=None, nbextensions_dir=None, sys Will check prefix/share/jupyter/nbextensions nbextensions_dir : str [optional] Specify absolute path of nbextensions directory explicitly. + sys_prefix : bool [default: False] + Install into the sys.prefix, i.e. environment """ nbext = _get_nbextension_dir(user=user, sys_prefix=sys_prefix, prefix=prefix, nbextensions_dir=nbextensions_dir) # make sure nbextensions dir exists @@ -240,6 +242,7 @@ def install_nbextension_python(package, overwrite=False, symlink=False, return full_dests + def uninstall_nbextension(dest, require, user=False, sys_prefix=False, prefix=None, nbextensions_dir=None, logger=None): """Uninstall a Javascript extension of the notebook @@ -290,7 +293,10 @@ def uninstall_nbextension(dest, require, user=False, sys_prefix=False, prefix=No def uninstall_nbextension_python(package, user=False, sys_prefix=False, prefix=None, nbextensions_dir=None, logger=None): - """Uninstall an nbextension bundled in a Python package.""" + """Uninstall an nbextension bundled in a Python package. + + See parameters of `install_nbextension_python` + """ m, nbexts = _get_nbextension_metadata(package) for nbext in nbexts: dest = nbext['dest'] @@ -301,8 +307,28 @@ def uninstall_nbextension_python(package, prefix=prefix, nbextensions_dir=nbextensions_dir, logger=logger) -def _set_nbextension_state(section, require, state, user, sys_prefix, - logger=None): +def _set_nbextension_state(section, require, state, + user=False, sys_prefix=False, logger=None): + """Set whether the section's frontend should require the named nbextension + + Returns True if the final state is the one requested. + + Parameters + ---------- + section : string + The section of the server to change, one of NBCONFIG_SECTIONS + require : string + An importable AMD module inside the nbextensions static path + state : bool + The state in which to leave the extension + user : bool [default: False] + Whether to check the user's .ipython/nbextensions directory. + Otherwise check a system-wide install (e.g. /usr/local/share/jupyter/nbextensions). + sys_prefix : bool [default: False] + Install into the sys.prefix, i.e. environment + logger : Jupyter logger [optional] + Logger instance to use + """ config_dir = os.path.join( _get_config_dir(user=user, sys_prefix=sys_prefix), 'nbconfig') cm = BaseJSONConfigManager(config_dir=config_dir) @@ -313,12 +339,30 @@ def _set_nbextension_state(section, require, state, user, sys_prefix, require )) cm.update(section, {"load_extensions": {require: state}}) + return cm.get(section).get(require) == state def _set_nbextension_state_python(state, package, user, sys_prefix, logger=None): - """ - Enable or disable a nbextension + """Enable or disable some nbextensions stored in a python package + + Returns a list of whether the state was achieved (i.e. changed, or was + already right) + + Parameters + ---------- + + state : Bool + Whether the extensions should be enabled + package : str + Importable Python package (no dotted-notation!) exposing the + magic-named `_jupyter_nbextension_paths` function + user : bool [default: False] + Whether to enable in the user's nbextensions directory. + sys_prefix : bool [default: False] + Enable/disable in the sys.prefix, i.e. environment + logger : Jupyter logger [optional] + Logger instance to use """ m, nbexts = _get_nbextension_metadata(package) return [_set_nbextension_state(section=nbext["section"], @@ -329,14 +373,52 @@ def _set_nbextension_state_python(state, package, user, sys_prefix, for nbext in nbexts] -def enable_nbextension(section, require, user, sys_prefix, logger=None): +def enable_nbextension(section, require, user=False, sys_prefix=False, + logger=None): + """Enable a named nbextension + + Returns True if the final state is the one requested. + + Parameters + ---------- + + section : string + The section of the server to change, one of NBCONFIG_SECTIONS + require : string + An importable AMD module inside the nbextensions static path + user : bool [default: False] + Whether to enable in the user's nbextensions directory. + sys_prefix : bool [default: False] + Whether to enable in the sys.prefix, i.e. environment + logger : Jupyter logger [optional] + Logger instance to use + """ return _set_nbextension_state(section=section, require=require, state=True, user=user, sys_prefix=sys_prefix, logger=logger) -def disable_nbextension(section, require, user, sys_prefix, logger=None): +def disable_nbextension(section, require, user=False, sys_prefix=False, + logger=None): + """Disable a named nbextension + + Returns True if the final state is the one requested. + + Parameters + ---------- + + section : string + The section of the server to change, one of NBCONFIG_SECTIONS + require : string + An importable AMD module inside the nbextensions static path + user : bool [default: False] + Whether to enable in the user's nbextensions directory. + sys_prefix : bool [default: False] + Whether to enable in the sys.prefix, i.e. environment + logger : Jupyter logger [optional] + Logger instance to use + """ return _set_nbextension_state(section=section, require=require, state=False, user=user, sys_prefix=sys_prefix, @@ -345,19 +427,63 @@ def disable_nbextension(section, require, user, sys_prefix, logger=None): def enable_nbextension_python(package, user=False, sys_prefix=False, logger=None): - """Enable an nbextension associated with a Python package.""" + """Enable some nbextensions associated with a Python package. + + Returns a list of whether the state was achieved (i.e. changed, or was + already right) + + Parameters + ---------- + + package : str + Importable Python package (no dotted-notation!) exposing the + magic-named `_jupyter_nbextension_paths` function + user : bool [default: False] + Whether to enable in the user's nbextensions directory. + sys_prefix : bool [default: False] + Whether to enable in the sys.prefix, i.e. environment + logger : Jupyter logger [optional] + Logger instance to use + """ return _set_nbextension_state_python(True, package, user, sys_prefix, logger=logger) def disable_nbextension_python(package, user=False, sys_prefix=False, logger=None): - """Disable an nbextension associated with a Python package.""" + """Disable some nbextensions associated with a Python package. + + Returns True if the final state is the one requested. + + Parameters + ---------- + + package : str + Importable Python package (no dotted-notation!) exposing the + magic-named `_jupyter_nbextension_paths` function + user : bool [default: False] + Whether to enable in the user's nbextensions directory. + sys_prefix : bool [default: False] + Whether to enable in the sys.prefix, i.e. environment + logger : Jupyter logger [optional] + Logger instance to use + """ return _set_nbextension_state_python(False, package, user, sys_prefix, logger=logger) def validate_nbextension(require, logger=None): + """Validate a named nbextension. + + Looks across all of the nbextension directories. + + Returns a list of warnings. + + require : str + require.js path used to load the extension + logger : Jupyter logger [optional] + Logger instance to use + """ warnings = [] infos = [] @@ -467,7 +593,7 @@ _base_flags = { _base_flags['python'] = _base_flags['py'] class BaseNBExtensionApp(JupyterApp): - + """Base nbextension installer app""" _log_formatter_cls = LogFormatter flags = _base_flags version = __version__ @@ -480,10 +606,12 @@ class BaseNBExtensionApp(JupyterApp): verbose = Any(None, config=True, help="DEPRECATED: Verbosity level") def _verbose_changed(self): + """Warn about verbosity changes""" import warnings warnings.warn("`verbose` traits of `{}` has been deprecated, has no effects and will be removed in notebook 5.0.".format(type(self).__name__), DeprecationWarning) def _log_format_default(self): + """A default format for messages""" return "%(message)s" @@ -539,9 +667,11 @@ class InstallNBExtensionApp(BaseNBExtensionApp): destination = Unicode('', config=True, help="Destination for the copy or symlink") def _config_file_name_default(self): + """The default config file name.""" return 'jupyter_notebook_config' def install_extensions(self): + """Perform the installation of nbextension(s)""" if len(self.extra_args)>1: raise ValueError("only one nbextension allowed at a time. Call multiple times to install multiple extensions.") @@ -558,6 +688,7 @@ class InstallNBExtensionApp(BaseNBExtensionApp): ) def start(self): + """Perform the App's function as configured""" if not self.extra_args: sys.exit('Please specify an nbextension to install') else: @@ -592,9 +723,11 @@ class UninstallNBExtensionApp(BaseNBExtensionApp): destination = Unicode('', config=True, help="Destination for the copy or symlink") def _config_file_name_default(self): + """The default config file name.""" return 'jupyter_notebook_config' def uninstall_extensions(self): + """Uninstall some nbextensions""" kwargs = { 'user': self.user, 'sys_prefix': self.sys_prefix, @@ -625,7 +758,7 @@ class UninstallNBExtensionApp(BaseNBExtensionApp): class ToggleNBExtensionApp(BaseNBExtensionApp): - + """A base class for apps that enable/disable extensions""" name = "jupyter nbextension enable/disable" version = __version__ description = "Enable/disable an nbextension using frontend configuration files." @@ -639,9 +772,21 @@ class ToggleNBExtensionApp(BaseNBExtensionApp): _toggle_value = None def _config_file_name_default(self): + """The default config file name.""" return 'jupyter_notebook_config' def toggle_nbextension_python(self, package): + """Toggle some extensions in an importable Python package. + + Returns a list of booleans indicating whether the state was changed as + requested. + + Parameters + ---------- + package : str + Importable Python package (no dotted-notation!) exposing the + magic-named `_jupyter_nbextension_paths` function + """ toggle = (enable_nbextension_python if self._toggle_value else disable_nbextension_python) return toggle(package, @@ -650,6 +795,15 @@ class ToggleNBExtensionApp(BaseNBExtensionApp): logger=self.log) def toggle_nbextension(self, require): + """Toggle some a named nbextension by require-able AMD module. + + Returns whether the state was changed as requested. + + Parameters + ---------- + require : str + require.js path used to load the nbextension + """ toggle = (enable_nbextension if self._toggle_value else disable_nbextension) return toggle(self.section, require, @@ -668,26 +822,27 @@ class ToggleNBExtensionApp(BaseNBExtensionApp): class EnableNBExtensionApp(ToggleNBExtensionApp): - + """An App that enables nbextensions""" name = "jupyter nbextension enable" description = "Enable an nbextension using frontend configuration files." _toggle_value = True class DisableNBExtensionApp(ToggleNBExtensionApp): - + """An App that disables nbextensions""" name = "jupyter nbextension disable" description = "Disable an nbextension using frontend configuration files." _toggle_value = None class ListNBExtensionsApp(BaseNBExtensionApp): - + """An App that lists and validates nbextensions""" name = "jupyter nbextension list" version = __version__ description = "List all nbextensions known by the configuration system" def list_nbextensions(self): + """List all the nbextensions""" config_dirs = [os.path.join(p, 'nbconfig') for p in jupyter_config_path()] for config_dir in config_dirs: @@ -706,6 +861,7 @@ class ListNBExtensionsApp(BaseNBExtensionApp): validate_nbextension(require, logger=self.log) def start(self): + """Perform the App's functions as configured""" self.list_nbextensions() @@ -718,7 +874,7 @@ jupyter nbextension uninstall --py # uninstall an nbextension in """ class NBExtensionApp(BaseNBExtensionApp): - + """Base jupyter nbextension command entry point""" name = "jupyter nbextension" version = __version__ description = "Work with Jupyter notebook extensions" @@ -733,6 +889,7 @@ class NBExtensionApp(BaseNBExtensionApp): ) def start(self): + """Perform the App's functions as configured""" super(NBExtensionApp, self).start() # The above should have called a subcommand and raised NoStart; if we From a17b7021ab9157ad0383e05ac170a0ffa53b2baf Mon Sep 17 00:00:00 2001 From: Nicholas Bollweg Date: Thu, 10 Mar 2016 12:04:24 -0500 Subject: [PATCH 2/2] docstrings for everyone :tada: --- notebook/nbextensions.py | 117 ++++++++++++++++++++++++++++++++++++--- 1 file changed, 108 insertions(+), 9 deletions(-) diff --git a/notebook/nbextensions.py b/notebook/nbextensions.py index dcb6c10e4..3f74a4096 100644 --- a/notebook/nbextensions.py +++ b/notebook/nbextensions.py @@ -65,7 +65,7 @@ def check_nbextension(files, user=False, prefix=None, nbextensions_dir=None, sys files : list(paths) a list of relative paths within nbextensions. user : bool [default: False] - Whether to check the user's .ipython/nbextensions directory. + Whether to check the user's .jupyter/nbextensions directory. Otherwise check a system-wide install (e.g. /usr/local/share/jupyter/nbextensions). prefix : str [optional] Specify install prefix, if it should differ from default (e.g. /usr/local). @@ -322,7 +322,7 @@ def _set_nbextension_state(section, require, state, state : bool The state in which to leave the extension user : bool [default: False] - Whether to check the user's .ipython/nbextensions directory. + Whether to check the user's .jupyter/nbextensions directory. Otherwise check a system-wide install (e.g. /usr/local/share/jupyter/nbextensions). sys_prefix : bool [default: False] Install into the sys.prefix, i.e. environment @@ -905,7 +905,20 @@ main = NBExtensionApp.launch_instance def _should_copy(src, dest, logger=None): - """Should a file be copied?""" + """Should a file be copied, if it doesn't exist, or is newer? + + Returns whether the file needs to be updated. + + Parameters + ---------- + + src : string + A path that should exist from which to copy a file + src : string + A path that might exist to which to copy a file + logger : Jupyter logger [optional] + Logger instance to use + """ if not os.path.exists(dest): return True if os.stat(src).st_mtime - os.stat(dest).st_mtime > 1e-6: @@ -920,7 +933,18 @@ def _should_copy(src, dest, logger=None): def _maybe_copy(src, dest, logger=None): - """Copy a file if it needs updating.""" + """Copy a file if it needs updating. + + Parameters + ---------- + + src : string + A path that should exist from which to copy a file + src : string + A path that might exist to which to copy a file + logger : Jupyter logger [optional] + Logger instance to use + """ if _should_copy(src, dest, logger=logger): if logger: logger.info("Copying: %s -> %s" % (src, dest)) @@ -928,7 +952,16 @@ def _maybe_copy(src, dest, logger=None): def _safe_is_tarfile(path): - """Safe version of is_tarfile, return False on IOError.""" + """Safe version of is_tarfile, return False on IOError. + + Returns whether the file exists and is a tarfile. + + Parameters + ---------- + + path : string + A path that might not exist and or be a tarfile + """ try: return tarfile.is_tarfile(path) except IOError: @@ -936,7 +969,20 @@ def _safe_is_tarfile(path): def _get_nbextension_dir(user=False, sys_prefix=False, prefix=None, nbextensions_dir=None): - """Return the nbextension directory specified""" + """Return the nbextension directory specified + + Parameters + ---------- + + user : bool [default: False] + Get the user's .jupyter/nbextensions directory + sys_prefix : bool [default: False] + Get sys.prefix, i.e. ~/.envs/my-env/share/jupyter/nbextensions + prefix : str [optional] + Get custom prefix + nbextensions_dir : str [optional] + Get what you put in + """ if sum(map(bool, [user, prefix, nbextensions_dir, sys_prefix])) > 1: raise ArgumentConflict("cannot specify more than one of user, sys_prefix, prefix, or nbextensions_dir") if user: @@ -953,7 +999,10 @@ def _get_nbextension_dir(user=False, sys_prefix=False, prefix=None, nbextensions def _nbextension_dirs(): - """The possible locations of nbextensions.""" + """The possible locations of nbextensions. + + Returns a list of known base extension locations + """ return [ pjoin(jupyter_data_dir(), u'nbextensions'), pjoin(ENV_JUPYTER_PATH[0], u'nbextensions'), @@ -962,6 +1011,18 @@ def _nbextension_dirs(): def _get_config_dir(user=False, sys_prefix=False): + """Get the location of config files for the current context + + Returns the string to the enviornment + + Parameters + ---------- + + user : bool [default: False] + Get the user's .jupyter config directory + sys_prefix : bool [default: False] + Get sys.prefix, i.e. ~/.envs/my-env/etc/jupyter + """ if user and sys_prefix: raise ArgumentConflict("Cannot specify more than one of user or sys_prefix") if user: @@ -974,6 +1035,22 @@ def _get_config_dir(user=False, sys_prefix=False): def _get_nbextension_metadata(package): + """Get the list of nbextension paths associated with a python package. + + Returns a tuple of (the module, [{ + 'section': 'notebook', + 'src': 'mockextension', + 'dest': '_mockdestination', + 'require': '_mockdestination/index' + }]) + + Parameters + ---------- + + package : str + Importable Python package (no dotted-notation!) exposing the + magic-named `_jupyter_nbextension_paths` function + """ m = __import__(package) if not hasattr(m, '_jupyter_nbextension_paths'): raise KeyError('The Python package {} is not a valid nbextension'.format(package)) @@ -982,17 +1059,39 @@ def _get_nbextension_metadata(package): def _read_config_data(user=False, sys_prefix=False): + """Get the config for the current context + + Returns the string to the enviornment + + Parameters + ---------- + + user : bool [default: False] + Get the user's .jupyter config directory + sys_prefix : bool [default: False] + Get sys.prefix, i.e. ~/.envs/my-env/etc/jupyter + """ config_dir = _get_config_dir(user=user, sys_prefix=sys_prefix) config_man = BaseJSONConfigManager(config_dir=config_dir) return config_man.get('jupyter_notebook_config') def _write_config_data(data, user=False, sys_prefix=False): + """Update the config for the current context + + Parameters + ---------- + data : object + An object which can be accepted by ConfigManager.update + user : bool [default: False] + Get the user's .jupyter config directory + sys_prefix : bool [default: False] + Get sys.prefix, i.e. ~/.envs/my-env/etc/jupyter + """ config_dir = _get_config_dir(user=user, sys_prefix=sys_prefix) config_man = BaseJSONConfigManager(config_dir=config_dir) config_man.update('jupyter_notebook_config', data) - + if __name__ == '__main__': main() -