1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165
|
# -*- coding: utf-8 -*-
# input-remapper - GUI for device specific keyboard mappings
# Copyright (C) 2025 sezanzeb <b8x45ygc9@mozmail.com>
#
# This file is part of input-remapper.
#
# input-remapper is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# input-remapper is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with input-remapper. If not, see <https://www.gnu.org/licenses/>.
"""Logging setup for input-remapper."""
import logging
import time
from typing import cast
from inputremapper.logging.formatter import ColorfulFormatter
COMMIT_HASH = ""
start = time.time()
previous_key_debug_log = None
previous_write_debug_log = None
class Logger(logging.Logger):
def debug_mapping_handler(self, mapping_handler):
"""Parse the structure of a mapping_handler and log it."""
if not self.isEnabledFor(logging.DEBUG):
return
lines_and_indent = self._parse_mapping_handler(mapping_handler)
for line in lines_and_indent:
indent = " "
msg = indent * line[1] + line[0]
self._log(logging.DEBUG, msg, args=None)
def write(self, key, uinput):
"""Log that an event is being written
Parameters
----------
key
anything that can be string formatted, but usually a tuple of
(type, code, value) tuples
"""
# pylint: disable=protected-access
if not self.isEnabledFor(logging.DEBUG):
return
global previous_write_debug_log
str_key = repr(key)
str_key = str_key.replace(",)", ")")
msg = f'Writing {str_key} to "{uinput.name}"'
if msg == previous_write_debug_log:
# avoid some super spam from EV_ABS events
return
previous_write_debug_log = msg
self._log(logging.DEBUG, msg, args=None, stacklevel=2)
def _parse_mapping_handler(self, mapping_handler):
indent = 0
lines_and_indent = []
while True:
if isinstance(mapping_handler, list):
for sub_handler in mapping_handler:
sub_list = self._parse_mapping_handler(sub_handler)
for line in sub_list:
line[1] += indent
lines_and_indent.extend(sub_list)
break
lines_and_indent.append([repr(mapping_handler), indent])
try:
mapping_handler = mapping_handler.child
except AttributeError:
break
indent += 1
return lines_and_indent
def is_debug(self) -> bool:
"""True, if the logger is currently in DEBUG mode."""
return self.level <= logging.DEBUG
def log_info(self, name: str = "input-remapper") -> None:
"""Log version and name to the console."""
logger.info(
"%s %s %s https://github.com/sezanzeb/input-remapper",
name,
VERSION,
COMMIT_HASH,
)
if EVDEV_VERSION:
logger.info("python-evdev %s", EVDEV_VERSION)
if self.is_debug():
logger.warning(
"Debug level will log all your keystrokes! Do not post this "
"output in the internet if you typed in sensitive or private "
"information with your device!"
)
def update_verbosity(self, debug: bool) -> None:
"""Set the logging verbosity according to the settings object."""
if debug:
self.setLevel(logging.DEBUG)
else:
self.setLevel(logging.INFO)
for handler in self.handlers:
handler.setFormatter(ColorfulFormatter(debug))
@classmethod
def bootstrap_logger(cls):
# https://github.com/python/typeshed/issues/1801
logging.setLoggerClass(cls)
logger = cast(cls, logging.getLogger("input-remapper"))
handler = logging.StreamHandler()
handler.setFormatter(ColorfulFormatter(False))
logger.addHandler(handler)
logger.setLevel(logging.INFO)
logging.getLogger("asyncio").setLevel(logging.WARNING)
return logger
logger = Logger.bootstrap_logger()
# using pkg_resources to figure out the version fails in many cases,
# so we hardcode it instead
VERSION = "2.2.0"
EVDEV_VERSION = None
try:
# pkg_resources very commonly fails/breaks
import pkg_resources
EVDEV_VERSION = pkg_resources.require("evdev")[0].version
except Exception as error:
# there have been pkg_resources.DistributionNotFound and
# pkg_resources.ContextualVersionConflict errors so far.
# We can safely ignore all Exceptions here
logger.info("Could not figure out the version")
logger.debug(error)
# check if the version is something like 1.5.0-beta or 1.5.0-beta.5
IS_BETA = "beta" in VERSION
|