Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.8/site-packages/nbconvert/preprocessors/clearmetadata.py: 35%
37 statements
« prev ^ index » next coverage.py v7.2.7, created at 2023-06-03 06:10 +0000
« prev ^ index » next coverage.py v7.2.7, created at 2023-06-03 06:10 +0000
1"""Module containing a preprocessor that removes metadata from code cells"""
3# Copyright (c) IPython Development Team.
4# Distributed under the terms of the Modified BSD License.
6from traitlets import Bool, Set
8from .base import Preprocessor
11class ClearMetadataPreprocessor(Preprocessor):
12 """
13 Removes all the metadata from all code cells in a notebook.
14 """
16 clear_cell_metadata = Bool(
17 True,
18 help=("Flag to choose if cell metadata is to be cleared in addition to notebook metadata."),
19 ).tag(config=True)
20 clear_notebook_metadata = Bool(
21 True,
22 help=("Flag to choose if notebook metadata is to be cleared in addition to cell metadata."),
23 ).tag(config=True)
24 preserve_nb_metadata_mask = Set(
25 [("language_info", "name")],
26 help=(
27 "Indicates the key paths to preserve when deleting metadata "
28 "across both cells and notebook metadata fields. Tuples of "
29 "keys can be passed to preserved specific nested values"
30 ),
31 ).tag(config=True)
32 preserve_cell_metadata_mask = Set(
33 help=(
34 "Indicates the key paths to preserve when deleting metadata "
35 "across both cells and notebook metadata fields. Tuples of "
36 "keys can be passed to preserved specific nested values"
37 )
38 ).tag(config=True)
40 def current_key(self, mask_key):
41 """Get the current key for a mask key."""
42 if isinstance(mask_key, str):
43 return mask_key
44 elif len(mask_key) == 0:
45 # Safeguard
46 return None
47 else:
48 return mask_key[0]
50 def current_mask(self, mask):
51 """Get the current mask for a mask."""
52 return {self.current_key(k) for k in mask if self.current_key(k) is not None}
54 def nested_masks(self, mask):
55 """Get the nested masks for a mask."""
56 return {
57 self.current_key(k[0]): k[1:]
58 for k in mask
59 if k and not isinstance(k, str) and len(k) > 1
60 }
62 def nested_filter(self, items, mask):
63 """Get the nested filter for items given a mask."""
64 keep_current = self.current_mask(mask)
65 keep_nested_lookup = self.nested_masks(mask)
66 for k, v in items:
67 keep_nested = keep_nested_lookup.get(k)
68 if k in keep_current:
69 if keep_nested is not None:
70 if isinstance(v, dict):
71 yield k, dict(self.nested_filter(v.items(), keep_nested))
72 else:
73 yield k, v
75 def preprocess_cell(self, cell, resources, cell_index):
76 """
77 All the code cells are returned with an empty metadata field.
78 """
79 if self.clear_cell_metadata and cell.cell_type == "code": # noqa
80 # Remove metadata
81 if "metadata" in cell:
82 cell.metadata = dict(
83 self.nested_filter(cell.metadata.items(), self.preserve_cell_metadata_mask)
84 )
85 return cell, resources
87 def preprocess(self, nb, resources):
88 """
89 Preprocessing to apply on each notebook.
91 Must return modified nb, resources.
93 Parameters
94 ----------
95 nb : NotebookNode
96 Notebook being converted
97 resources : dictionary
98 Additional resources used in the conversion process. Allows
99 preprocessors to pass variables into the Jinja engine.
100 """
101 nb, resources = super().preprocess(nb, resources)
102 if self.clear_notebook_metadata and "metadata" in nb:
103 nb.metadata = dict(
104 self.nested_filter(nb.metadata.items(), self.preserve_nb_metadata_mask)
105 )
106 return nb, resources