Coverage for hookee/util.py: 93.85%
65 statements
« prev ^ index » next coverage.py v7.3.4, created at 2023-12-27 17:55 +0000
« prev ^ index » next coverage.py v7.3.4, created at 2023-12-27 17:55 +0000
1import inspect
2import json
3import logging
4import os
5import sys
7import click
9__author__ = "Alex Laird"
10__copyright__ = "Copyright 2023, Alex Laird"
11__version__ = "2.0.8"
13from defusedxml.minidom import parseString
15logger = logging.getLogger(__name__)
18class PrintUtil:
19 """
20 An object that provides helper methods for logging output. If :class:`~hookee.conf.Config`'s ``click_logging`` is
21 ``True`` (which will happen by default if a :class:`click.Context` is found to be active), this logging will be
22 done through ``click``, otherwise the ``hookee`` logger will be used.
24 If ``click_logging`` is disabled, output sent through this utility can still be interacted with by ensuring the a
25 logger is setup. For example, this would add a handler to the ``hookee`` logger that just logs output back to
26 the console:
28 .. code-block:: python
30 import logging
32 logger = logging.getLogger("hookee")
33 logger.setLevel(logging.INFO)
34 logging.getLogger().addHandler(logging.StreamHandler())
36 :var config: The ``hookee`` configuration.
37 :vartype config: Config
38 """
40 def __init__(self, config):
41 self.config = config
43 @property
44 def console_width(self):
45 return self.config.get("console_width")
47 @property
48 def header_color(self):
49 return self.config.get("header_color")
51 @property
52 def default_color(self):
53 return self.config.get("default_color")
55 @property
56 def request_color(self):
57 return self.config.get("request_color")
59 def print_config_update(self, msg):
60 self.print_basic("\n--> {}\n".format(msg), color=self.header_color)
62 def print_open_header(self, title, delimiter="-", color=None):
63 """
64 Log an opening header with a title and a new line before and after.
66 :param title: The header title.
67 :type title: str
68 :param delimiter: The title of the XML blob.
69 :type delimiter: str, optional
70 :param color: The color to make the text.
71 :type color: str, optional
72 """
73 if color is None:
74 color = self.header_color
76 width = int((self.console_width - len(title)) / 2)
78 self.print_basic()
79 self.print_basic("{}{}{}".format(delimiter * width, title, delimiter * width), color=color, bold=True)
80 self.print_basic()
82 def print_close_header(self, delimiter="-", color=None, blank_line=True):
83 """
84 Log a closing header with an optional new line before.
86 :param delimiter: The title of the XML blob.
87 :type delimiter: str
88 :param color: The color to make the text.
89 :type color: str, optional
90 :param blank_line: ``True`` if a blank line should precede the closing header.
91 :type blank_line: bool
92 """
93 if color is None:
94 color = self.header_color
96 if blank_line:
97 self.print_basic()
98 self.print_basic(delimiter * self.console_width, color=color, bold=True)
100 def print_dict(self, title, data, color=None):
101 """
102 Log formatted dictionary data.
104 :param title: The title of the XML blob.
105 :type title: str
106 :param data: A dictionary.
107 :type data: dict
108 :param color: The color to make the text.
109 :type color: str, optional
110 """
111 if color is None:
112 color = self.default_color
114 self.print_basic("{}: {}".format(title, json.dumps(data, indent=4)), color=color)
116 def print_xml(self, title, data, color=None):
117 """
118 Log formatted XML.
120 :param title: The title of the XML blob.
121 :type title: str
122 :param data: An XML string.
123 :type data: str
124 :param color: The color to make the text.
125 :type color: str, optional
126 """
127 if color is None:
128 color = self.default_color
130 self.print_basic("{}: {}".format(title, parseString(data).toprettyxml()), color=color)
132 def print_basic(self, msg="", color=None, bold=False, print_when_logging=False):
133 """
134 Log a basic message. The message will be logged via ``click``, if ``click_logging`` is enabled in
135 :class:`~hookee.conf.Config`, or appended to the logger.
137 :param msg: The update to print.
138 :type msg: str, optional
139 :param color: The color to make the text.
140 :type color: str, optional
141 :param bold: ``True`` if the output should be bold.
142 :type bold: bool, optional
143 :param print_when_logging: ``True`` if, when ``click_logging`` is ``False``, ``msg`` should print to the
144 console instead of appending to the logger.
145 :type print_when_logging: bool, optional
146 """
147 if color is None:
148 color = self.default_color
150 if self.config.click_logging:
151 click.secho(msg, fg=color, bold=bold)
152 elif not print_when_logging:
153 logger.info(msg)
154 else:
155 print(msg)
158def python36_gte():
159 """
160 Check if running on a Python 3.6 or higher interpreter.
162 :return: ``True`` if Python 3.6 or higher.
163 :rtype: bool
164 """
165 return sys.version_info >= (3, 6)
168def get_functions(mod):
169 """
170 Get a list of functions for the given module.
172 :param mod: The module to inspect for functions.
173 :type mod: types.ModuleType
174 :return: The list of functions.
175 :rtype: list[types.FunctionType]
176 """
177 return [o[0] for o in inspect.getmembers(mod, inspect.isfunction)]
180def get_args(func):
181 """
182 Get a list of args for the given function.
184 :param func: The function to inspect for args.
185 :type func: types.FunctionType
186 :return: The list of args.
187 :rtype: list[str]
188 """
189 return inspect.getfullargspec(func)[0]
192def get_module_name(module):
193 """
194 Get the name of the module from the basename of its path.
196 :param module: The module.
197 :type module: types.ModuleType
198 :return: The base name of the module.
199 :rtype: str
200 """
201 return os.path.splitext(os.path.basename(module.__file__))[0]