Create module for high-level xfconf ops
This commit is contained in:
parent
cce38c94c6
commit
5310496238
121
xion.py
121
xion.py
|
@ -1,61 +1,74 @@
|
|||
from ctypes import byref, cdll, c_char_p, c_void_p, POINTER
|
||||
import argparse
|
||||
import json
|
||||
|
||||
from xfconf import Xfconf
|
||||
|
||||
|
||||
class Xfconf:
|
||||
"""Xfconf library interface."""
|
||||
|
||||
def __init__(self, libxfconf="libxfconf-0.so.2",
|
||||
libglib="libglib-2.0.so.0"):
|
||||
self.lib = cdll.LoadLibrary(libxfconf)
|
||||
self.glib = cdll.LoadLibrary(libglib)
|
||||
self.set_foreign_functions()
|
||||
|
||||
def set_foreign_functions(self):
|
||||
self._ff_init = self.lib.xfconf_init
|
||||
self._ff_shutdown = self.lib.xfconf_shutdown
|
||||
self._ff_list_channels = self.lib.xfconf_list_channels
|
||||
self._ff_list_channels.restype = POINTER(c_void_p)
|
||||
self._ff_channel_get = self.lib.xfconf_channel_get
|
||||
self._ff_channel_get.argtypes = (c_char_p,)
|
||||
self._ff_channel_get.restype = c_void_p
|
||||
self._ff_channel_get_properties = self.lib.xfconf_channel_get_properties
|
||||
self._ff_channel_get_properties.argtypes = (c_void_p, c_char_p)
|
||||
self._ff_channel_get_properties.restype = c_void_p
|
||||
|
||||
def init(self):
|
||||
err = c_void_p()
|
||||
if not self._ff_init(byref(err)):
|
||||
raise XfconfError("xfconf_init: error")
|
||||
|
||||
def shutdown(self):
|
||||
self._ff_shutdown()
|
||||
|
||||
def list_channels(self):
|
||||
channels = self._ff_list_channels()
|
||||
i = 0
|
||||
while channels[i] is not None:
|
||||
yield c_char_p(channels[i]).value.decode()
|
||||
i += 1
|
||||
self.glib.g_strfreev(channels)
|
||||
|
||||
def get_channel(self, name):
|
||||
return self._ff_channel_get(name.encode())
|
||||
|
||||
def list_properties(self, channel, base=None):
|
||||
table = self._ff_channel_get_properties(channel, None)
|
||||
print(table)
|
||||
self.glib.g_hash_table_destroy(table)
|
||||
DEFAULT_FILE_PATH = "xion.json"
|
||||
|
||||
|
||||
def main():
|
||||
argparser = argparse.ArgumentParser()
|
||||
argparser.add_argument("--xq-path", type=str,
|
||||
help="Optional path to xion-query")
|
||||
argparser.add_argument("-e", "--export", type=str, nargs=2,
|
||||
metavar=("channel", "root"),
|
||||
help="Channel and root to export")
|
||||
argparser.add_argument("-f", "--file", type=str,
|
||||
help="JSON file for import/export")
|
||||
args = argparser.parse_args()
|
||||
|
||||
class XfconfError(Exception):
|
||||
pass
|
||||
xion = Xion(xq=args.xq_path)
|
||||
if args.export:
|
||||
channel, root = args.export
|
||||
tree = xion.build_tree(channel, root)
|
||||
if tree is None:
|
||||
print("Failed to build config tree.")
|
||||
return
|
||||
if args.file:
|
||||
output_path = args.file
|
||||
else:
|
||||
print(f"No output file, using {DEFAULT_FILE_PATH}.")
|
||||
output_path = DEFAULT_FILE_PATH
|
||||
xion.export_tree(tree, output_path)
|
||||
|
||||
|
||||
xfconf = Xfconf()
|
||||
xfconf.init()
|
||||
for channel_name in xfconf.list_channels():
|
||||
print(channel_name)
|
||||
channel = xfconf.get_channel("xfce4-keyboard-shortcuts")
|
||||
xfconf.list_properties(channel)
|
||||
xfconf.shutdown()
|
||||
class Xion:
|
||||
|
||||
def __init__(self, xq=None):
|
||||
self.xfconf = Xfconf(xq=xq)
|
||||
|
||||
def build_tree(self, channel, root="/"):
|
||||
"""Return a dict of configs in this channel, filtering on root.
|
||||
|
||||
Return None on error.
|
||||
"""
|
||||
props = self.xfconf.get_property_list(channel, root=root)
|
||||
if props is None:
|
||||
print(f"Failed to get property list for channel {channel}.")
|
||||
return None
|
||||
tree = {}
|
||||
for prop_name in props:
|
||||
prop = self.xfconf.get_property(channel, prop_name)
|
||||
if prop is None:
|
||||
print(f"Failed to get property {prop_name}.")
|
||||
return None
|
||||
if isinstance(prop, list):
|
||||
leaf = [Xion._build_prop_leaf(p) for p in prop]
|
||||
else:
|
||||
leaf = Xion._build_prop_leaf(prop)
|
||||
tree[prop_name] = leaf
|
||||
return tree
|
||||
|
||||
def export_tree(self, tree, output_path):
|
||||
"""Export a config tree as a sorted JSON file."""
|
||||
with open(output_path, "wt") as output_file:
|
||||
json.dump(tree, output_file, indent=2, sort_keys=True)
|
||||
|
||||
@staticmethod
|
||||
def _build_prop_leaf(prop):
|
||||
return {"type": prop.gtype, "value": str(prop.value)}
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
|
|
Loading…
Reference in a new issue