86 lines
3.4 KiB
Python
86 lines
3.4 KiB
Python
|
"""Module containing a preprocessor that removes metadata from code cells"""
|
||
|
|
||
|
# Copyright (c) IPython Development Team.
|
||
|
# Distributed under the terms of the Modified BSD License.
|
||
|
|
||
|
from traitlets import Bool, Set
|
||
|
from .base import Preprocessor
|
||
|
|
||
|
class ClearMetadataPreprocessor(Preprocessor):
|
||
|
"""
|
||
|
Removes all the metadata from all code cells in a notebook.
|
||
|
"""
|
||
|
|
||
|
clear_cell_metadata = Bool(True,
|
||
|
help=("Flag to choose if cell metadata is to be cleared "
|
||
|
"in addition to notebook metadata.")).tag(config=True)
|
||
|
clear_notebook_metadata = Bool(True,
|
||
|
help=("Flag to choose if notebook metadata is to be cleared "
|
||
|
"in addition to cell metadata.")).tag(config=True)
|
||
|
preserve_nb_metadata_mask = Set([('language_info', 'name')],
|
||
|
help=("Indicates the key paths to preserve when deleting metadata "
|
||
|
"across both cells and notebook metadata fields. Tuples of "
|
||
|
"keys can be passed to preserved specific nested values")).tag(config=True)
|
||
|
preserve_cell_metadata_mask = Set(
|
||
|
help=("Indicates the key paths to preserve when deleting metadata "
|
||
|
"across both cells and notebook metadata fields. Tuples of "
|
||
|
"keys can be passed to preserved specific nested values")).tag(config=True)
|
||
|
|
||
|
def current_key(self, mask_key):
|
||
|
if isinstance(mask_key, str):
|
||
|
return mask_key
|
||
|
elif len(mask_key) == 0:
|
||
|
# Safeguard
|
||
|
return None
|
||
|
else:
|
||
|
return mask_key[0]
|
||
|
|
||
|
def current_mask(self, mask):
|
||
|
return { self.current_key(k) for k in mask if self.current_key(k) is not None }
|
||
|
|
||
|
def nested_masks(self, mask):
|
||
|
return { self.current_key(k[0]): k[1:] for k in mask if k and not isinstance(k, str) and len(k) > 1 }
|
||
|
|
||
|
def nested_filter(self, items, mask):
|
||
|
keep_current = self.current_mask(mask)
|
||
|
keep_nested_lookup = self.nested_masks(mask)
|
||
|
for k, v in items:
|
||
|
keep_nested = keep_nested_lookup.get(k)
|
||
|
if k in keep_current:
|
||
|
if keep_nested is not None:
|
||
|
if isinstance(v, dict):
|
||
|
yield k, dict(self.nested_filter(v.items(), keep_nested))
|
||
|
else:
|
||
|
yield k, v
|
||
|
|
||
|
def preprocess_cell(self, cell, resources, cell_index):
|
||
|
"""
|
||
|
All the code cells are returned with an empty metadata field.
|
||
|
"""
|
||
|
if self.clear_cell_metadata:
|
||
|
if cell.cell_type == 'code':
|
||
|
# Remove metadata
|
||
|
if 'metadata' in cell:
|
||
|
cell.metadata = dict(self.nested_filter(cell.metadata.items(), self.preserve_cell_metadata_mask))
|
||
|
return cell, resources
|
||
|
|
||
|
def preprocess(self, nb, resources):
|
||
|
"""
|
||
|
Preprocessing to apply on each notebook.
|
||
|
|
||
|
Must return modified nb, resources.
|
||
|
|
||
|
Parameters
|
||
|
----------
|
||
|
nb : NotebookNode
|
||
|
Notebook being converted
|
||
|
resources : dictionary
|
||
|
Additional resources used in the conversion process. Allows
|
||
|
preprocessors to pass variables into the Jinja engine.
|
||
|
"""
|
||
|
nb, resources = super().preprocess(nb, resources)
|
||
|
if self.clear_notebook_metadata:
|
||
|
if 'metadata' in nb:
|
||
|
nb.metadata = dict(self.nested_filter(nb.metadata.items(), self.preserve_nb_metadata_mask))
|
||
|
return nb, resources
|