solaar: improve imports and guard Gtk, etc imports with correct version

solaar: move imports to top of files

solaar: move more imports to top of files

solaar: guard Gtk, etc imports with correct version
This commit is contained in:
Peter F. Patel-Schneider 2024-02-10 23:13:29 -05:00
parent 17e6463950
commit d1c899d6da
14 changed files with 64 additions and 56 deletions

View File

@ -33,6 +33,11 @@ from collections import namedtuple
from threading import Thread from threading import Thread
from time import sleep from time import sleep
import gi
gi.require_version('Gdk', '3.0')
from gi.repository import GLib # NOQA: E402
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
native_implementation = 'hidapi' native_implementation = 'hidapi'
@ -257,7 +262,7 @@ def _match(action, device, filterfn):
device['hidpp_long'] = True device['hidpp_long'] = True
except HIDError as e: # noqa: F841 except HIDError as e: # noqa: F841
if logger.isEnabledFor(logging.INFO): if logger.isEnabledFor(logging.INFO):
logger.info(f"Error opening device {device['path']} ({bus_id}/{vid:04X}/{pid:04X}) for hidpp check: {e}") logger.info(f"Error opening device {device['path']} ({bus_id}/{vid:04X}/{pid:04X}) for hidpp check: {e}") # noqa
finally: finally:
if device_handle: if device_handle:
close(device_handle) close(device_handle)
@ -279,8 +284,8 @@ def _match(action, device, filterfn):
d_info = DeviceInfo( d_info = DeviceInfo(
path=device['path'].decode(), path=device['path'].decode(),
bus_id=bus_id, bus_id=bus_id,
vendor_id=f'{vid:04X}', vendor_id=f'{vid:04X}', # noqa
product_id=f'{pid:04X}', product_id=f'{pid:04X}', # noqa
interface=None, interface=None,
driver=None, driver=None,
manufacturer=device['manufacturer_string'], manufacturer=device['manufacturer_string'],
@ -297,8 +302,8 @@ def _match(action, device, filterfn):
d_info = DeviceInfo( d_info = DeviceInfo(
path=device['path'].decode(), path=device['path'].decode(),
bus_id=None, bus_id=None,
vendor_id=f'{vid:04X}', vendor_id=f'{vid:04X}', # noqa
product_id=f'{pid:04X}', product_id=f'{pid:04X}', # noqa
interface=None, interface=None,
driver=None, driver=None,
manufacturer=None, manufacturer=None,
@ -323,7 +328,6 @@ def find_paired_node_wpid(receiver_path, index):
def monitor_glib(callback, filterfn): def monitor_glib(callback, filterfn):
from gi.repository import GLib
def device_callback(action, device): def device_callback(action, device):
# print(f"device_callback({action}): {device}") # print(f"device_callback({action}): {device}")

View File

@ -16,13 +16,16 @@
## with this program; if not, write to the Free Software Foundation, Inc., ## with this program; if not, write to the Free Software Foundation, Inc.,
## 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. ## 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
import argparse
import os import os
import os.path
import readline
import sys import sys
import time import time
from binascii import hexlify, unhexlify from binascii import hexlify, unhexlify
from select import select as _select from select import select as _select
from threading import Lock from threading import Lock, Thread
import hidapi as _hid import hidapi as _hid
@ -176,7 +179,6 @@ def _open(args):
def _parse_arguments(): def _parse_arguments():
import argparse
arg_parser = argparse.ArgumentParser() arg_parser = argparse.ArgumentParser()
arg_parser.add_argument('--history', help='history file (default ~/.hidconsole-history)') arg_parser.add_argument('--history', help='history file (default ~/.hidconsole-history)')
arg_parser.add_argument('--hidpp', action='store_true', help='ensure input data is a valid HID++ request') arg_parser.add_argument('--hidpp', action='store_true', help='ensure input data is a valid HID++ request')
@ -196,9 +198,7 @@ def main():
if interactive: if interactive:
print('.. Press ^C/^D to exit, or type hex bytes to write to the device.') print('.. Press ^C/^D to exit, or type hex bytes to write to the device.')
import readline
if args.history is None: if args.history is None:
import os.path
args.history = os.path.join(os.path.expanduser('~'), '.hidconsole-history') args.history = os.path.join(os.path.expanduser('~'), '.hidconsole-history')
try: try:
readline.read_history_file(args.history) readline.read_history_file(args.history)
@ -207,7 +207,6 @@ def main():
pass pass
try: try:
from threading import Thread
t = Thread(target=_continuous_read, args=(handle, )) t = Thread(target=_continuous_read, args=(handle, ))
t.daemon = True t.daemon = True
t.start() t.start()

View File

@ -35,12 +35,18 @@ from select import select as _select
from time import sleep from time import sleep
from time import time as _timestamp from time import time as _timestamp
import gi
from hid_parser import ReportDescriptor as _ReportDescriptor
from pyudev import Context as _Context from pyudev import Context as _Context
from pyudev import Device as _Device from pyudev import Device as _Device
from pyudev import DeviceNotFoundError from pyudev import DeviceNotFoundError
from pyudev import Devices as _Devices from pyudev import Devices as _Devices
from pyudev import Monitor as _Monitor from pyudev import Monitor as _Monitor
gi.require_version('Gdk', '3.0')
from gi.repository import GLib # NOQA: E402
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
native_implementation = 'udev' native_implementation = 'udev'
@ -105,9 +111,6 @@ def _match(action, device, filterfn):
return # these are devices connected through a receiver so don't pick them up here return # these are devices connected through a receiver so don't pick them up here
try: # if report descriptor does not indicate HID++ capabilities then this device is not of interest to Solaar try: # if report descriptor does not indicate HID++ capabilities then this device is not of interest to Solaar
from hid_parser import ReportDescriptor as _ReportDescriptor
# from hid_parser import Usage as _Usage
hidpp_short = hidpp_long = False hidpp_short = hidpp_long = False
devfile = '/sys' + hid_device.get('DEVPATH') + '/report_descriptor' devfile = '/sys' + hid_device.get('DEVPATH') + '/report_descriptor'
with fileopen(devfile, 'rb') as fd: with fileopen(devfile, 'rb') as fd:
@ -236,8 +239,6 @@ def find_paired_node_wpid(receiver_path, index):
def monitor_glib(callback, filterfn): def monitor_glib(callback, filterfn):
from gi.repository import GLib
c = _Context() c = _Context()
# already existing devices # already existing devices

View File

@ -18,14 +18,20 @@
import ctypes as _ctypes import ctypes as _ctypes
import logging import logging
import math
import numbers
import os as _os import os as _os
import os.path as _path import os.path as _path
import platform as _platform import platform as _platform
import socket
import subprocess
import sys as _sys import sys as _sys
import time as _time import time as _time
from math import sqrt as _sqrt import dbus
from struct import unpack as _unpack import gi
import keysyms.keysymdef as _keysymdef
import psutil
# There is no evdev on macOS or Windows. Diversion will not work without # There is no evdev on macOS or Windows. Diversion will not work without
# it but other Solaar functionality is available. # it but other Solaar functionality is available.
@ -34,9 +40,8 @@ if _platform.system() in ('Darwin', 'Windows'):
else: else:
import evdev import evdev
import dbus from math import sqrt as _sqrt
import keysyms.keysymdef as _keysymdef from struct import unpack as _unpack
import psutil
from yaml import add_representer as _yaml_add_representer from yaml import add_representer as _yaml_add_representer
from yaml import dump_all as _yaml_dump_all from yaml import dump_all as _yaml_dump_all
@ -46,8 +51,6 @@ from .common import NamedInt
from .hidpp20 import FEATURE as _F from .hidpp20 import FEATURE as _F
from .special_keys import CONTROL as _CONTROL from .special_keys import CONTROL as _CONTROL
import gi # isort:skip
gi.require_version('Gdk', '3.0') # isort:skip gi.require_version('Gdk', '3.0') # isort:skip
from gi.repository import Gdk, GLib # NOQA: E402 # isort:skip from gi.repository import Gdk, GLib # NOQA: E402 # isort:skip
@ -1082,7 +1085,6 @@ class Host(Condition):
def evaluate(self, feature, notification, device, status, last_result): def evaluate(self, feature, notification, device, status, last_result):
if logger.isEnabledFor(logging.DEBUG): if logger.isEnabledFor(logging.DEBUG):
logger.debug('evaluate condition: %s', self) logger.debug('evaluate condition: %s', self)
import socket
hostname = socket.getfqdn() hostname = socket.getfqdn()
return hostname.startswith(self.host) return hostname.startswith(self.host)
@ -1206,7 +1208,6 @@ class KeyPress(Action):
class MouseScroll(Action): class MouseScroll(Action):
def __init__(self, amounts, warn=True): def __init__(self, amounts, warn=True):
import numbers
if len(amounts) == 1 and isinstance(amounts[0], list): if len(amounts) == 1 and isinstance(amounts[0], list):
amounts = amounts[0] amounts = amounts[0]
if not (len(amounts) == 2 and all([isinstance(a, numbers.Number) for a in amounts])): if not (len(amounts) == 2 and all([isinstance(a, numbers.Number) for a in amounts])):
@ -1219,8 +1220,6 @@ class MouseScroll(Action):
return 'MouseScroll: ' + ' '.join([str(a) for a in self.amounts]) return 'MouseScroll: ' + ' '.join([str(a) for a in self.amounts])
def evaluate(self, feature, notification, device, status, last_result): def evaluate(self, feature, notification, device, status, last_result):
import math
import numbers
amounts = self.amounts amounts = self.amounts
if isinstance(last_result, numbers.Number): if isinstance(last_result, numbers.Number):
amounts = [math.floor(last_result * a) for a in self.amounts] amounts = [math.floor(last_result * a) for a in self.amounts]
@ -1328,7 +1327,6 @@ class Execute(Action):
return 'Execute: ' + ' '.join([a for a in self.args]) return 'Execute: ' + ' '.join([a for a in self.args])
def evaluate(self, feature, notification, device, status, last_result): def evaluate(self, feature, notification, device, status, last_result):
import subprocess
if logger.isEnabledFor(logging.INFO): if logger.isEnabledFor(logging.INFO):
logger.info('Execute action: %s', self.args) logger.info('Execute action: %s', self.args)
subprocess.Popen(self.args) subprocess.Popen(self.args)

View File

@ -19,6 +19,7 @@
# Logitech Unifying Receiver API. # Logitech Unifying Receiver API.
import logging import logging
import socket
import threading as _threading import threading as _threading
from struct import pack as _pack from struct import pack as _pack
@ -2003,7 +2004,6 @@ def get_host_names(device):
remaining = 0 remaining = 0
host_names[host] = (bool(status), name) host_names[host] = (bool(status), name)
# update the current host's name if it doesn't match the system name # update the current host's name if it doesn't match the system name
import socket
hostname = socket.gethostname().partition('.')[0] hostname = socket.gethostname().partition('.')[0]
if host_names[currentHost][1] != hostname: if host_names[currentHost][1] != hostname:
set_host_name(device, hostname, host_names[currentHost][1]) set_host_name(device, hostname, host_names[currentHost][1])

View File

@ -26,6 +26,7 @@ from threading import Timer as _Timer
import yaml as _yaml import yaml as _yaml
from gi.repository import GLib
from logitech_receiver.common import NamedInt as _NamedInt from logitech_receiver.common import NamedInt as _NamedInt
from solaar import __version__ from solaar import __version__
@ -142,7 +143,6 @@ def save(defer=False):
else: else:
with save_lock: with save_lock:
if not save_timer: if not save_timer:
from gi.repository import GLib
save_timer = _Timer(5.0, lambda: GLib.idle_add(do_save)) save_timer = _Timer(5.0, lambda: GLib.idle_add(do_save))
save_timer.start() save_timer.start()

View File

@ -18,6 +18,8 @@
## with this program; if not, write to the Free Software Foundation, Inc., ## with this program; if not, write to the Free Software Foundation, Inc.,
## 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. ## 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
import argparse
import faulthandler
import importlib import importlib
import logging import logging
import os.path import os.path
@ -26,8 +28,15 @@ import signal
import sys import sys
import tempfile import tempfile
from traceback import format_exc
import solaar.cli as _cli import solaar.cli as _cli
import solaar.configuration as _configuration
import solaar.i18n as _i18n import solaar.i18n as _i18n
import solaar.listener as _listener
import solaar.ui as _ui
import solaar.ui.common as _common
import solaar.upower as _upower
from solaar import NAME, __version__ from solaar import NAME, __version__
@ -52,7 +61,6 @@ temp = tempfile.NamedTemporaryFile(prefix='Solaar_', mode='w', delete=True)
def _parse_arguments(): def _parse_arguments():
import argparse
arg_parser = argparse.ArgumentParser( arg_parser = argparse.ArgumentParser(
prog=NAME.lower(), epilog='For more information see https://pwr-solaar.github.io/Solaar' prog=NAME.lower(), epilog='For more information see https://pwr-solaar.github.io/Solaar'
) )
@ -122,7 +130,6 @@ def _parse_arguments():
# On first SIGINT, dump threads to stderr; on second, exit # On first SIGINT, dump threads to stderr; on second, exit
def _handlesig(signl, stack): def _handlesig(signl, stack):
import faulthandler
signal.signal(signal.SIGINT, signal.SIG_DFL) signal.signal(signal.SIGINT, signal.SIG_DFL)
signal.signal(signal.SIGTERM, signal.SIG_DFL) signal.signal(signal.SIGTERM, signal.SIG_DFL)
@ -161,25 +168,18 @@ def main():
logger.warning('Solaar udev file not found in expected location') logger.warning('Solaar udev file not found in expected location')
logger.warning('See https://pwr-solaar.github.io/Solaar/installation for more information') logger.warning('See https://pwr-solaar.github.io/Solaar/installation for more information')
try: try:
import solaar.listener as listener _listener.setup_scanner(_ui.status_changed, _common.error_dialog)
import solaar.ui as ui
import solaar.ui.common as common
listener.setup_scanner(ui.status_changed, common.error_dialog)
import solaar.upower as _upower
if args.restart_on_wake_up: if args.restart_on_wake_up:
_upower.watch(listener.start_all, listener.stop_all) _upower.watch(_listener.start_all, _listener.stop_all)
else: else:
_upower.watch(lambda: listener.ping_all(True)) _upower.watch(lambda: _listener.ping_all(True))
import solaar.configuration as _configuration
_configuration.defer_saves = True # allow configuration saves to be deferred _configuration.defer_saves = True # allow configuration saves to be deferred
# main UI event loop # main UI event loop
ui.run_loop(listener.start_all, listener.stop_all, args.window != 'only', args.window != 'hide') _ui.run_loop(_listener.start_all, _listener.stop_all, args.window != 'only', args.window != 'hide')
except Exception: except Exception:
from traceback import format_exc
sys.exit('%s: error: %s' % (NAME.lower(), format_exc())) sys.exit('%s: error: %s' % (NAME.lower(), format_exc()))
temp.close() temp.close()

View File

@ -18,6 +18,10 @@
import gettext as _gettext import gettext as _gettext
import locale import locale
import os.path as _path
import sys as _sys
from glob import glob as _glob
from solaar import NAME as _NAME from solaar import NAME as _NAME
@ -27,13 +31,8 @@ from solaar import NAME as _NAME
def _find_locale_path(lc_domain): def _find_locale_path(lc_domain):
import os.path as _path
import sys as _sys
prefix_share = _path.normpath(_path.join(_path.realpath(_sys.path[0]), '..')) prefix_share = _path.normpath(_path.join(_path.realpath(_sys.path[0]), '..'))
src_share = _path.normpath(_path.join(_path.realpath(_sys.path[0]), '..', 'share')) src_share = _path.normpath(_path.join(_path.realpath(_sys.path[0]), '..', 'share'))
del _sys
from glob import glob as _glob
for location in prefix_share, src_share: for location in prefix_share, src_share:
mo_files = _glob(_path.join(location, 'locale', '*', 'LC_MESSAGES', lc_domain + '.mo')) mo_files = _glob(_path.join(location, 'locale', '*', 'LC_MESSAGES', lc_domain + '.mo'))

View File

@ -18,6 +18,7 @@
import errno as _errno import errno as _errno
import logging import logging
import subprocess
import time import time
from collections import namedtuple from collections import namedtuple
@ -390,7 +391,6 @@ def _process_add(device_info, retry):
except OSError as e: except OSError as e:
if e.errno == _errno.EACCES: if e.errno == _errno.EACCES:
try: try:
import subprocess
output = subprocess.check_output(['/usr/bin/getfacl', '-p', device_info.path], text=True) output = subprocess.check_output(['/usr/bin/getfacl', '-p', device_info.path], text=True)
if logger.isEnabledFor(logging.WARNING): if logger.isEnabledFor(logging.WARNING):
logger.warning('Missing permissions on %s\n%s.', device_info.path, output) logger.warning('Missing permissions on %s\n%s.', device_info.path, output)

View File

@ -21,7 +21,6 @@ import logging
import gi import gi
import yaml as _yaml import yaml as _yaml
from gi.repository import Gio, GLib, Gtk
from logitech_receiver.status import ALERT from logitech_receiver.status import ALERT
from solaar.i18n import _ from solaar.i18n import _
from solaar.tasks import TaskRunner as _TaskRunner from solaar.tasks import TaskRunner as _TaskRunner
@ -31,6 +30,8 @@ from solaar.ui.window import find_device
from . import diversion_rules, notify, tray, window from . import diversion_rules, notify, tray, window
gi.require_version('Gtk', '3.0') gi.require_version('Gtk', '3.0')
from gi.repository import Gio, GLib, Gtk # NOQA: E402
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
# #

View File

@ -18,9 +18,13 @@
import logging import logging
from gi.repository import GLib, Gtk import gi
from solaar.i18n import _ from solaar.i18n import _
gi.require_version('Gtk', '3.0')
from gi.repository import GLib, Gtk # NOQA: E402
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)

View File

@ -21,7 +21,8 @@ import traceback
from threading import Timer as _Timer from threading import Timer as _Timer
from gi.repository import Gdk, GLib, Gtk import gi
from logitech_receiver.hidpp20 import LEDEffectSetting as _LEDEffectSetting from logitech_receiver.hidpp20 import LEDEffectSetting as _LEDEffectSetting
from logitech_receiver.settings import KIND as _SETTING_KIND from logitech_receiver.settings import KIND as _SETTING_KIND
from logitech_receiver.settings import SENSITIVITY_IGNORE as _SENSITIVITY_IGNORE from logitech_receiver.settings import SENSITIVITY_IGNORE as _SENSITIVITY_IGNORE
@ -29,6 +30,9 @@ from solaar.i18n import _, ngettext
from .common import ui_async as _ui_async from .common import ui_async as _ui_async
gi.require_version('Gtk', '3.0')
from gi.repository import Gdk, GLib, Gtk # NOQA: E402
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
# #

View File

@ -21,6 +21,7 @@ import os
from time import time as _timestamp from time import time as _timestamp
import gi
import solaar.gtk as gtk import solaar.gtk as gtk
from gi.repository import GLib, Gtk from gi.repository import GLib, Gtk
@ -144,7 +145,6 @@ def _scroll(tray_icon, event, direction=None):
try: try:
import gi
try: try:
gi.require_version('AyatanaAppIndicator3', '0.1') gi.require_version('AyatanaAppIndicator3', '0.1')
from gi.repository import AyatanaAppIndicator3 as AppIndicator3 from gi.repository import AyatanaAppIndicator3 as AppIndicator3

View File

@ -2,6 +2,7 @@
import subprocess import subprocess
from glob import glob as _glob from glob import glob as _glob
from os.path import dirname as _dirname
try: try:
from setuptools import setup from setuptools import setup
@ -29,7 +30,6 @@ except Exception: # get commit from Ubuntu dpkg-parsechangelog
def _data_files(): def _data_files():
from os.path import dirname as _dirname
yield 'share/icons/hicolor/scalable/apps', _glob('share/solaar/icons/solaar*.svg') yield 'share/icons/hicolor/scalable/apps', _glob('share/solaar/icons/solaar*.svg')
yield 'share/icons/hicolor/32x32/apps', _glob('share/solaar/icons/solaar-light_*.png') yield 'share/icons/hicolor/32x32/apps', _glob('share/solaar/icons/solaar-light_*.png')
@ -41,8 +41,6 @@ def _data_files():
yield 'lib/udev/rules.d', ['rules.d/42-logitech-unify-permissions.rules'] yield 'lib/udev/rules.d', ['rules.d/42-logitech-unify-permissions.rules']
yield 'share/metainfo', ['share/solaar/io.github.pwr_solaar.solaar.metainfo.xml'] yield 'share/metainfo', ['share/solaar/io.github.pwr_solaar.solaar.metainfo.xml']
del _dirname
setup( setup(
name=NAME.lower(), name=NAME.lower(),