From 16c22a95ecbdcd581c92a6aadfc17ac8eb8cb1ab Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Fri, 9 Aug 2019 14:44:51 +1000 Subject: [PATCH] base: add a flag to control the config directory For testing it's a lot easier to just provide a /tmp/ directory than having to clear out the normal one that may contain useful drawings for debugging. Signed-off-by: Peter Hutterer --- tuhi.in | 6 ++++-- tuhi/base.py | 10 +++++++--- tuhi/config.py | 18 +++++++++++------- tuhigui/application.py | 21 ++++++++++++++++++++- tuhigui/config.py | 32 +++++++++++++++++++++----------- 5 files changed, 63 insertions(+), 24 deletions(-) diff --git a/tuhi.in b/tuhi.in index 5fa557b..c842812 100755 --- a/tuhi.in +++ b/tuhi.in @@ -11,6 +11,7 @@ # GNU General Public License for more details. # +import sys import os import subprocess @@ -21,9 +22,10 @@ tuhi_gui = os.path.join('@libexecdir@', 'tuhi-gui') @devel@ # NOQA if __name__ == '__main__': - tuhi = subprocess.Popen(tuhi_server) + args = sys.argv[1:] + tuhi = subprocess.Popen([tuhi_server] + args) try: - subprocess.run(tuhi_gui) + subprocess.run([tuhi_gui] + args) except KeyboardInterrupt: pass tuhi.terminate() diff --git a/tuhi/base.py b/tuhi/base.py index 0c84772..dc0f566 100644 --- a/tuhi/base.py +++ b/tuhi/base.py @@ -288,7 +288,7 @@ class Tuhi(GObject.Object): (GObject.SignalFlags.RUN_FIRST, None, ()), } - def __init__(self): + def __init__(self, config_dir=None): GObject.Object.__init__(self) self.server = TuhiDBusServer() self.server.connect('bus-name-acquired', self._on_tuhi_bus_name_acquired) @@ -299,7 +299,7 @@ class Tuhi(GObject.Object): self.bluez.connect('discovery-started', self._on_bluez_discovery_started) self.bluez.connect('discovery-stopped', self._on_bluez_discovery_stopped) - self.config = TuhiConfig() + self.config = TuhiConfig(config_dir) self.devices = {} @@ -427,6 +427,10 @@ def main(args=sys.argv): help='Show some debugging informations', action='store_true', default=False) + parser.add_argument('--config-dir', + help='Base directory for configuration', + type=str, + default=None) ns = parser.parse_args(args[1:]) if ns.verbose: @@ -434,7 +438,7 @@ def main(args=sys.argv): try: mainloop = GLib.MainLoop() - tuhi = Tuhi() + tuhi = Tuhi(config_dir=ns.config_dir) tuhi.connect('terminate', lambda tuhi: mainloop.quit()) mainloop.run() except KeyboardInterrupt: diff --git a/tuhi/config.py b/tuhi/config.py index d3f3da9..e7f61f1 100644 --- a/tuhi/config.py +++ b/tuhi/config.py @@ -23,7 +23,7 @@ from .wacom import Protocol logger = logging.getLogger('tuhi.config') -ROOT_PATH = os.path.join(xdg.BaseDirectory.xdg_data_home, 'tuhi') +DEFAULT_CONFIG_PATH = os.path.join(xdg.BaseDirectory.xdg_data_home, 'tuhi') def is_btaddr(addr): @@ -31,10 +31,14 @@ def is_btaddr(addr): class TuhiConfig(GObject.Object): - def __init__(self): + def __init__(self, config_dir=None): GObject.Object.__init__(self) + if config_dir is None: + config_dir = DEFAULT_CONFIG_PATH + self.config_dir = config_dir + logger.debug(f'Using config directory: {self.config_dir}') try: - os.mkdir(ROOT_PATH) + os.mkdir(config_dir) except FileExistsError: pass @@ -49,7 +53,7 @@ class TuhiConfig(GObject.Object): return self._devices def _scan_config_dir(self): - with os.scandir(ROOT_PATH) as it: + with os.scandir(self.config_dir) as it: for entry in it: if entry.is_file(): continue @@ -78,7 +82,7 @@ class TuhiConfig(GObject.Object): assert protocol != Protocol.UNKNOWN logger.debug(f'{address}: adding new config, UUID {uuid}') - path = os.path.join(ROOT_PATH, address) + path = os.path.join(self.config_dir, address) try: os.mkdir(path) except FileExistsError: @@ -115,7 +119,7 @@ class TuhiConfig(GObject.Object): return logger.debug(f'{address}: adding new drawing, timestamp {drawing.timestamp}') - path = os.path.join(ROOT_PATH, address, f'{drawing.timestamp}.json') + path = os.path.join(self.config_dir, address, f'{drawing.timestamp}.json') with open(path, 'w') as f: f.write(drawing.to_json()) @@ -127,7 +131,7 @@ class TuhiConfig(GObject.Object): if address not in self.devices: return drawings - configdir = os.path.join(ROOT_PATH, address) + configdir = os.path.join(self.config_dir, address) with os.scandir(configdir) as it: for entry in it: if not entry.is_file(): diff --git a/tuhigui/application.py b/tuhigui/application.py index 6207474..2e89dac 100644 --- a/tuhigui/application.py +++ b/tuhigui/application.py @@ -13,6 +13,7 @@ from gi.repository import Gio, GLib, Gtk from .window import MainWindow +from .config import Config import gi gi.require_version("Gio", "2.0") @@ -22,8 +23,13 @@ gi.require_version("Gtk", "3.0") class Application(Gtk.Application): def __init__(self): super().__init__(application_id='org.freedesktop.Tuhi', - flags=Gio.ApplicationFlags.FLAGS_NONE) + flags=Gio.ApplicationFlags.HANDLES_COMMAND_LINE) GLib.set_application_name('Tuhi') + self.add_main_option('config-dir', 0, + GLib.OptionFlags.NONE, + GLib.OptionArg.STRING, + 'path to configuration directory', + '/path/to/config-dir') self._tuhi = None def do_startup(self): @@ -34,6 +40,19 @@ class Application(Gtk.Application): window = MainWindow(application=self) window.present() + def do_command_line(self, command_line): + options = command_line.get_options_dict() + # convert GVariantDict -> GVariant -> dict + options = options.end().unpack() + + try: + Config.set_base_path(options['config-dir']) + except KeyError: + pass + + self.activate() + return 0 + def _build_app_menu(self): actions = [('about', self._about), ('quit', self._quit), diff --git a/tuhigui/config.py b/tuhigui/config.py index a32ca41..f7b02bd 100644 --- a/tuhigui/config.py +++ b/tuhigui/config.py @@ -22,15 +22,17 @@ from pathlib import Path logger = logging.getLogger('tuhi.gui.config') -ROOT_PATH = Path(xdg.BaseDirectory.xdg_data_home, 'tuhi') +DEFAULT_CONFIG_PATH = Path(xdg.BaseDirectory.xdg_data_home, 'tuhi') class Config(GObject.Object): _config_obj = None + _base_path = DEFAULT_CONFIG_PATH def __init__(self): super().__init__() - self.path = Path(ROOT_PATH, 'tuhigui.ini') + self.path = Path(self._base_path, 'tuhigui.ini') + self.base_path = self._base_path self.config = configparser.ConfigParser() # Don't lowercase options self.config.optionxform = str @@ -46,10 +48,10 @@ class Config(GObject.Object): self.config.read(self.path) def _load_cached_drawings(self): - if not ROOT_PATH.exists(): + if not self.base_path.exists(): return - for filename in ROOT_PATH.glob('*.json'): + for filename in self.base_path.glob('*.json'): with open(filename) as fd: self._drawings.append(json.load(fd)) self.notify('drawings') @@ -84,15 +86,15 @@ class Config(GObject.Object): def add_drawing(self, timestamp, json_string): '''Add a drawing JSON with the given timestamp to the backend storage. This will update self.drawings.''' - ROOT_PATH.mkdir(parents=True, exist_ok=True) + self.base_path.mkdir(parents=True, exist_ok=True) - path = Path(ROOT_PATH, f'{timestamp}.json') + path = Path(self.base_path, f'{timestamp}.json') if path.exists(): return # Tuhi may still cache files we've 'deleted' locally. These need to # be ignored because they're still technically deleted. - deleted = Path(ROOT_PATH, f'{timestamp}.json.deleted') + deleted = Path(self.base_path, f'{timestamp}.json.deleted') if deleted.exists(): return @@ -105,22 +107,30 @@ class Config(GObject.Object): def delete_drawing(self, timestamp): # We don't delete json files immediately, we just rename them # so we can resurrect them in the future if need be. - path = Path(ROOT_PATH, f'{timestamp}.json') - target = Path(ROOT_PATH, f'{timestamp}.json.deleted') + path = Path(self.base_path, f'{timestamp}.json') + target = Path(self.base_path, f'{timestamp}.json.deleted') path.rename(target) self._drawings = [d for d in self._drawings if d['timestamp'] != timestamp] self.notify('drawings') def undelete_drawing(self, timestamp): - path = Path(ROOT_PATH, f'{timestamp}.json') - target = Path(ROOT_PATH, f'{timestamp}.json.deleted') + path = Path(self.base_path, f'{timestamp}.json') + target = Path(self.base_path, f'{timestamp}.json.deleted') target.rename(path) with open(path) as fd: self._drawings.append(json.load(fd)) self.notify('drawings') + @classmethod + def set_base_path(cls, path): + if cls._config_obj is not None: + logger.error('Trying to set config base path but we already have the singleton object') + return + + cls._base_path = Path(path) + @classmethod def instance(cls): if cls._config_obj is None: