Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.11/site-packages/nbconvert/preprocessors/clearmetadata.py: 37%

Shortcuts on this page

r m x   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

38 statements  

1"""Module containing a preprocessor that removes metadata from code cells""" 

2 

3# Copyright (c) IPython Development Team. 

4# Distributed under the terms of the Modified BSD License. 

5 

6from traitlets import Bool, Set 

7 

8from .base import Preprocessor 

9 

10 

11class ClearMetadataPreprocessor(Preprocessor): 

12 """ 

13 Removes all the metadata from all code cells in a notebook. 

14 """ 

15 

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) 

39 

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 if len(mask_key) == 0: 

45 # Safeguard 

46 return None 

47 return mask_key[0] 

48 

49 def current_mask(self, mask): 

50 """Get the current mask for a mask.""" 

51 return {self.current_key(k) for k in mask if self.current_key(k) is not None} 

52 

53 def nested_masks(self, mask): 

54 """Get the nested masks for a mask.""" 

55 return { 

56 self.current_key(k[0]): k[1:] 

57 for k in mask 

58 if k and not isinstance(k, str) and len(k) > 1 

59 } 

60 

61 def nested_filter(self, items, mask): 

62 """Get the nested filter for items given a mask.""" 

63 keep_current = self.current_mask(mask) 

64 keep_nested_lookup = self.nested_masks(mask) 

65 for k, v in items: 

66 keep_nested = keep_nested_lookup.get(k) 

67 if k in keep_current: 

68 if keep_nested is not None: 

69 if isinstance(v, dict): 

70 yield k, dict(self.nested_filter(v.items(), keep_nested)) 

71 else: 

72 yield k, v 

73 

74 def preprocess_cell(self, cell, resources, cell_index): 

75 """ 

76 All the code cells are returned with an empty metadata field. 

77 """ 

78 if self.clear_cell_metadata and cell.cell_type == "code": # noqa: SIM102 

79 # Remove metadata 

80 if "metadata" in cell: 

81 cell.metadata = dict( 

82 self.nested_filter(cell.metadata.items(), self.preserve_cell_metadata_mask) 

83 ) 

84 return cell, resources 

85 

86 def preprocess(self, nb, resources): 

87 """ 

88 Preprocessing to apply on each notebook. 

89 

90 Must return modified nb, resources. 

91 

92 Parameters 

93 ---------- 

94 nb : NotebookNode 

95 Notebook being converted 

96 resources : dictionary 

97 Additional resources used in the conversion process. Allows 

98 preprocessors to pass variables into the Jinja engine. 

99 """ 

100 nb, resources = super().preprocess(nb, resources) 

101 if self.clear_notebook_metadata and "metadata" in nb: 

102 nb.metadata = dict( 

103 self.nested_filter(nb.metadata.items(), self.preserve_nb_metadata_mask) 

104 ) 

105 return nb, resources