Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.8/site-packages/pygments/formatters/__init__.py: 43%

84 statements  

« prev     ^ index     » next       coverage.py v7.2.2, created at 2023-03-26 07:45 +0000

1""" 

2 pygments.formatters 

3 ~~~~~~~~~~~~~~~~~~~ 

4 

5 Pygments formatters. 

6 

7 :copyright: Copyright 2006-2022 by the Pygments team, see AUTHORS. 

8 :license: BSD, see LICENSE for details. 

9""" 

10 

11import re 

12import sys 

13import types 

14import fnmatch 

15from os.path import basename 

16 

17from pygments.formatters._mapping import FORMATTERS 

18from pygments.plugin import find_plugin_formatters 

19from pygments.util import ClassNotFound 

20 

21__all__ = ['get_formatter_by_name', 'get_formatter_for_filename', 

22 'get_all_formatters', 'load_formatter_from_file'] + list(FORMATTERS) 

23 

24_formatter_cache = {} # classes by name 

25_pattern_cache = {} 

26 

27 

28def _fn_matches(fn, glob): 

29 """Return whether the supplied file name fn matches pattern filename.""" 

30 if glob not in _pattern_cache: 

31 pattern = _pattern_cache[glob] = re.compile(fnmatch.translate(glob)) 

32 return pattern.match(fn) 

33 return _pattern_cache[glob].match(fn) 

34 

35 

36def _load_formatters(module_name): 

37 """Load a formatter (and all others in the module too).""" 

38 mod = __import__(module_name, None, None, ['__all__']) 

39 for formatter_name in mod.__all__: 

40 cls = getattr(mod, formatter_name) 

41 _formatter_cache[cls.name] = cls 

42 

43 

44def get_all_formatters(): 

45 """Return a generator for all formatter classes.""" 

46 # NB: this returns formatter classes, not info like get_all_lexers(). 

47 for info in FORMATTERS.values(): 

48 if info[1] not in _formatter_cache: 

49 _load_formatters(info[0]) 

50 yield _formatter_cache[info[1]] 

51 for _, formatter in find_plugin_formatters(): 

52 yield formatter 

53 

54 

55def find_formatter_class(alias): 

56 """Lookup a formatter by alias. 

57 

58 Returns None if not found. 

59 """ 

60 for module_name, name, aliases, _, _ in FORMATTERS.values(): 

61 if alias in aliases: 

62 if name not in _formatter_cache: 

63 _load_formatters(module_name) 

64 return _formatter_cache[name] 

65 for _, cls in find_plugin_formatters(): 

66 if alias in cls.aliases: 

67 return cls 

68 

69 

70def get_formatter_by_name(_alias, **options): 

71 """Lookup and instantiate a formatter by alias. 

72 

73 Raises ClassNotFound if not found. 

74 """ 

75 cls = find_formatter_class(_alias) 

76 if cls is None: 

77 raise ClassNotFound("no formatter found for name %r" % _alias) 

78 return cls(**options) 

79 

80 

81def load_formatter_from_file(filename, formattername="CustomFormatter", 

82 **options): 

83 """Load a formatter from a file. 

84 

85 This method expects a file located relative to the current working 

86 directory, which contains a class named CustomFormatter. By default, 

87 it expects the Formatter to be named CustomFormatter; you can specify 

88 your own class name as the second argument to this function. 

89 

90 Users should be very careful with the input, because this method 

91 is equivalent to running eval on the input file. 

92 

93 Raises ClassNotFound if there are any problems importing the Formatter. 

94 

95 .. versionadded:: 2.2 

96 """ 

97 try: 

98 # This empty dict will contain the namespace for the exec'd file 

99 custom_namespace = {} 

100 with open(filename, 'rb') as f: 

101 exec(f.read(), custom_namespace) 

102 # Retrieve the class `formattername` from that namespace 

103 if formattername not in custom_namespace: 

104 raise ClassNotFound('no valid %s class found in %s' % 

105 (formattername, filename)) 

106 formatter_class = custom_namespace[formattername] 

107 # And finally instantiate it with the options 

108 return formatter_class(**options) 

109 except OSError as err: 

110 raise ClassNotFound('cannot read %s: %s' % (filename, err)) 

111 except ClassNotFound: 

112 raise 

113 except Exception as err: 

114 raise ClassNotFound('error when loading custom formatter: %s' % err) 

115 

116 

117def get_formatter_for_filename(fn, **options): 

118 """Lookup and instantiate a formatter by filename pattern. 

119 

120 Raises ClassNotFound if not found. 

121 """ 

122 fn = basename(fn) 

123 for modname, name, _, filenames, _ in FORMATTERS.values(): 

124 for filename in filenames: 

125 if _fn_matches(fn, filename): 

126 if name not in _formatter_cache: 

127 _load_formatters(modname) 

128 return _formatter_cache[name](**options) 

129 for cls in find_plugin_formatters(): 

130 for filename in cls.filenames: 

131 if _fn_matches(fn, filename): 

132 return cls(**options) 

133 raise ClassNotFound("no formatter found for file name %r" % fn) 

134 

135 

136class _automodule(types.ModuleType): 

137 """Automatically import formatters.""" 

138 

139 def __getattr__(self, name): 

140 info = FORMATTERS.get(name) 

141 if info: 

142 _load_formatters(info[0]) 

143 cls = _formatter_cache[info[1]] 

144 setattr(self, name, cls) 

145 return cls 

146 raise AttributeError(name) 

147 

148 

149oldmod = sys.modules[__name__] 

150newmod = _automodule(__name__) 

151newmod.__dict__.update(oldmod.__dict__) 

152sys.modules[__name__] = newmod 

153del newmod.newmod, newmod.oldmod, newmod.sys, newmod.types