This commit is contained in:
boyska 2022-01-25 12:12:06 +01:00
parent 2e8e785616
commit a10aeceab4

View file

@ -21,8 +21,15 @@ import re
import stat
from contextlib import closing
from gi import require_version
require_version("Gtk", "3.0")
from gi.repository import Gtk, Gdk, GLib, GObject # pylint:disable=wrong-import-position
from gi.repository import (
Gtk,
Gdk,
GLib,
GObject,
) # pylint:disable=wrong-import-position
try:
require_version("Wnck", "3.0")
from gi.repository import Wnck
@ -35,6 +42,7 @@ if sys.version_info.major == 3:
else:
# py 2.x
from ConfigParser import SafeConfigParser # pylint:disable=import-error
# In python 2, ENOENT is sometimes IOError and sometimes OSError. Catch
# both by catching their immediate superclass exception EnvironmentError.
FileNotFoundError = EnvironmentError # pylint: disable=redefined-builtin
@ -78,7 +86,11 @@ class suppress_if_errno(object):
# exactly reproduce the limitations of the CPython interpreter.
#
# See http://bugs.python.org/issue12029 for more details
return exctype is not None and issubclass(exctype, self._exceptions) and excinst.errno == self._exc_val
return (
exctype is not None
and issubclass(exctype, self._exceptions)
and excinst.errno == self._exc_val
)
class ClipsterError(Exception):
@ -88,7 +100,6 @@ class ClipsterError(Exception):
Exception.__init__(self, args)
class Daemon(object):
"""Handles clipboard events, client requests, stores history."""
@ -104,12 +115,12 @@ class Daemon(object):
self.primary = Gtk.Clipboard.get(Gdk.SELECTION_PRIMARY)
self.clipboard = Gtk.Clipboard.get(Gdk.SELECTION_CLIPBOARD)
self.boards = {"PRIMARY": [], "CLIPBOARD": []}
self.pid_file = self.config.get('calippo', 'pid_file')
self.pid_file = self.config.get("calippo", "pid_file")
self.client_msgs = {}
# Flag to indicate that the in-memory history should be flushed to disk
self.update_history_file = False
# Flag whether next clipboard change should be ignored
self.ignore_next = {'PRIMARY': False, 'CLIPBOARD': False}
self.ignore_next = {"PRIMARY": False, "CLIPBOARD": False}
self.whitelist_classes = self.blacklist_classes = []
self.command = command
@ -136,10 +147,8 @@ class Daemon(object):
self.window = Gtk.Window(type=Gtk.WindowType.POPUP)
# Handle clipboard changes
self.p_id = self.primary.connect('owner-change',
self.owner_change)
self.c_id = self.clipboard.connect('owner-change',
self.owner_change)
self.p_id = self.primary.connect("owner-change", self.owner_change)
self.c_id = self.clipboard.connect("owner-change", self.owner_change)
# Handle unix signals
GLib.unix_signal_add(GLib.PRIORITY_HIGH, signal.SIGINT, self.exit)
GLib.unix_signal_add(GLib.PRIORITY_HIGH, signal.SIGTERM, self.exit)
@ -147,14 +156,13 @@ class Daemon(object):
Gtk.main()
def prepare_files(self):
"""Ensure that all files and sockets used
by the daemon are available."""
# Create the calippo dir if necessary
with suppress_if_errno(FileExistsError, errno.EEXIST):
os.makedirs(self.config.get('calippo', 'data_dir'))
os.makedirs(self.config.get("calippo", "data_dir"))
# check for existing pid_file, and tidy up if appropriate
with suppress_if_errno(FileNotFoundError, errno.ENOENT):
@ -168,7 +176,9 @@ class Daemon(object):
try:
# Do nothing, but raise an error if no such process
os.kill(pid, 0)
raise ClipsterError("Daemon already running: pid {}".format(pid))
raise ClipsterError(
"Daemon already running: pid {}".format(pid)
)
except ProcessLookupError as exc:
if exc.errno != errno.ESRCH:
raise
@ -182,7 +192,7 @@ class Daemon(object):
logging.debug("owner-change event!")
selection = str(event.selection)
logging.debug("selection: %s", selection)
active = self.config.get('calippo', 'active_selections').split(',')
active = self.config.get("calippo", "active_selections").split(",")
if selection not in active:
return
@ -277,14 +287,21 @@ def find_config():
# Set a default directory for calippo files
# https://specifications.freedesktop.org/basedir-spec/basedir-spec-latest.html
xdg_config_dirs = os.environ.get('XDG_CONFIG_DIRS', '/etc/xdg').split(':')
xdg_config_dirs.insert(0, os.environ.get('XDG_CONFIG_HOME', os.path.join(os.environ.get('HOME'), ".config")))
xdg_data_home = os.environ.get('XDG_DATA_HOME', os.path.join(os.environ.get('HOME'), ".local/share"))
xdg_config_dirs = os.environ.get("XDG_CONFIG_DIRS", "/etc/xdg").split(":")
xdg_config_dirs.insert(
0,
os.environ.get(
"XDG_CONFIG_HOME", os.path.join(os.environ.get("HOME"), ".config")
),
)
xdg_data_home = os.environ.get(
"XDG_DATA_HOME", os.path.join(os.environ.get("HOME"), ".local/share")
)
data_dir = os.path.join(xdg_data_home, "calippo")
# Keep trying to define conf_dir, moving from local -> global
for path in xdg_config_dirs:
conf_dir = os.path.join(path, 'calippo')
conf_dir = os.path.join(path, "calippo")
if os.path.exists(conf_dir):
return conf_dir, data_dir
return "", data_dir
@ -300,8 +317,10 @@ def main():
args = parse_args()
# Enable logging
logging.basicConfig(format='%(levelname)s:%(message)s',
level=getattr(logging, args.log_level.upper()))
logging.basicConfig(
format="%(levelname)s:%(message)s",
level=getattr(logging, args.log_level.upper()),
)
logging.debug("Debugging Enabled.")
config = parse_config(args, data_dir, conf_dir)
@ -314,7 +333,7 @@ def safe_decode(data):
"""Convenience method to ensure everything is utf-8."""
try:
data = data.decode('utf-8')
data = data.decode("utf-8")
except (UnicodeDecodeError, UnicodeEncodeError, AttributeError):
pass
return data