Coverage for hookee/util.py: 93.85%

# Coverage for hookee/util.py : 93.85%

## 65 statements

Hot-keys on this page

r m x p toggle line displays

j k next/prev highlighted chunk

0 (zero) top of page

1 (one) first highlighted chunk

1 import inspect

2 import json

3 import logging

4 import os

5 import sys

6 import xml.dom.minidom

7

8 import click

9

10 __author__ = "Alex Laird"

11 __copyright__ = "Copyright 2020, Alex Laird"

12 __version__ = "2.0.0"

13

14 logger = logging.getLogger(__name__)

15

16

17 class PrintUtil:

18 """

19 An object that provides helper methods for logging output. If :class:`~hookee.conf.Config`'s ``click_logging`` is

20 ``True`` (which will happen by default if a :class:`click.Context` is found to be active), this logging will be

21 done through ``click``, otherwise the ``hookee`` logger will be used.

22

23 If ``click_logging`` is disabled, output sent through this utility can still be interacted with by ensuring the a

24 logger is setup. For example, this would add a handler to the ``hookee`` logger that just logs output back to

25 the console:

26

27 .. code-block:: python

28

29 import logging

30

31 logger = logging.getLogger("hookee")

32 logger.setLevel(logging.INFO)

33 logging.getLogger().addHandler(logging.StreamHandler())

34

35 :var config: The ``hookee`` configuration.

36 :vartype config: Config

37 """

38

39 def __init__(self, config):

40 self.config = config

41

42 @property

43 def console_width(self):

44 return self.config.get("console_width")

45

46 @property

47 def header_color(self):

48 return self.config.get("header_color")

49

50 @property

51 def default_color(self):

52 return self.config.get("default_color")

53

54 @property

55 def request_color(self):

56 return self.config.get("request_color")

57

58 def print_config_update(self, msg):

59 self.print_basic("\n--> {}\n".format(msg), color=self.header_color)

60

61 def print_open_header(self, title, delimiter="-", color=None):

62 """

63 Log an opening header with a title and a new line before and after.

64

65 :param title: The header title.

66 :type title: str

67 :param delimiter: The title of the XML blob.

68 :type delimiter: str, optional

69 :param color: The color to make the text.

70 :type color: str, optional

71 """

72 if color is None:

73 color = self.header_color

74

75 width = int((self.console_width - len(title)) / 2)

76

77 self.print_basic()

78 self.print_basic("{}{}{}".format(delimiter * width, title, delimiter * width), color=color, bold=True)

79 self.print_basic()

80

81 def print_close_header(self, delimiter="-", color=None, blank_line=True):

82 """

83 Log a closing header with an optional new line before.

84

85 :param delimiter: The title of the XML blob.

86 :type delimiter: str

87 :param color: The color to make the text.

88 :type color: str, optional

89 :param blank_line: ``True`` if a blank line should precede the closing header.

90 :type blank_line: bool

91 """

92 if color is None:

93 color = self.header_color

94

95 if blank_line:

96 self.print_basic()

97 self.print_basic(delimiter * self.console_width, color=color, bold=True)

98

99 def print_dict(self, title, data, color=None):

100 """

101 Log formatted dictionary data.

102

103 :param title: The title of the XML blob.

104 :type title: str

105 :param data: A dictionary.

106 :type data: dict

107 :param color: The color to make the text.

108 :type color: str, optional

109 """

110 if color is None:

111 color = self.default_color

112

113 self.print_basic("{}: {}".format(title, json.dumps(data, indent=4)), color=color)

114

115 def print_xml(self, title, data, color=None):

116 """

117 Log formatted XML.

118

119 :param title: The title of the XML blob.

120 :type title: str

121 :param data: An XML string.

122 :type data: str

123 :param color: The color to make the text.

124 :type color: str, optional

125 """

126 if color is None:

127 color = self.default_color

128

129 self.print_basic("{}: {}".format(title, xml.dom.minidom.parseString(data).toprettyxml()), color=color)

130

131 def print_basic(self, msg="", color=None, bold=False, print_when_logging=False):

132 """

133 Log a basic message. The message will be logged via ``click``, if ``click_logging`` is enabled in

134 :class:`~hookee.conf.Config`, or appended to the logger.

135

136 :param msg: The update to print.

137 :type msg: str, optional

138 :param color: The color to make the text.

139 :type color: str, optional

140 :param bold: ``True`` if the output should be bold.

141 :type bold: bool, optional

142 :param print_when_logging: ``True`` if, when ``click_logging`` is ``False``, ``msg`` should print to the

143 console instead of appending to the logger.

144 :type print_when_logging: bool, optional

145 """

146 if color is None:

147 color = self.default_color

148

149 if self.config.click_logging:

150 click.secho(msg, fg=color, bold=bold)

151 elif not print_when_logging:

152 logger.info(msg)

153 else:

154 print(msg)

155

156

157 def python36_gte():

158 """

159 Check if running on a Python 3.6 or higher interpreter.

160

161 :return: ``True`` if Python 3.6 or higher.

162 :rtype: bool

163 """

164 return sys.version_info >= (3, 6)

165

166

167 def get_functions(mod):

168 """

169 Get a list of functions for the given module.

170

171 :param mod: The module to inspect for functions.

172 :type mod: types.ModuleType

173 :return: The list of functions.

174 :rtype: list[types.FunctionType]

175 """

176 return [o[0] for o in inspect.getmembers(mod, inspect.isfunction)]

177

178

179 def get_args(func):

180 """

181 Get a list of args for the given function.

182

183 :param func: The function to inspect for args.

184 :type func: types.FunctionType

185 :return: The list of args.

186 :rtype: list[str]

187 """

188 return inspect.getfullargspec(func)[0]

189

190

191 def get_module_name(module):

192 """

193 Get the name of the module from the basename of its path.

194

195 :param module: The module.

196 :type module: types.ModuleType

197 :return: The base name of the module.

198 :rtype: str

199 """

200 return os.path.splitext(os.path.basename(module.__file__))[0]