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

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

45 # Safeguard 

46 return None 

47 else: 

48 return mask_key[0] 

49 

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} 

53 

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 } 

61 

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 

74 

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 

86 

87 def preprocess(self, nb, resources): 

88 """ 

89 Preprocessing to apply on each notebook. 

90 

91 Must return modified nb, resources. 

92 

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