mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2025-02-23 18:52:09 +01:00
Make the gconf schema parser a class
This commit is contained in:
parent
57613df216
commit
aac33fb2a8
@ -22,6 +22,8 @@
|
|||||||
|
|
||||||
# TODO: add alias support for choices
|
# TODO: add alias support for choices
|
||||||
# choices: 'this-is-an-alias' = 'real', 'other', 'real'
|
# choices: 'this-is-an-alias' = 'real', 'other', 'real'
|
||||||
|
# TODO: we don't support migrating a pair from a gconf schema. It has yet to be
|
||||||
|
# seen in real-world usage, though.
|
||||||
|
|
||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
@ -348,106 +350,6 @@ class GSettingsSchemaKey:
|
|||||||
######################################
|
######################################
|
||||||
|
|
||||||
|
|
||||||
def map_gconf_type_to_variant_type(gconftype, gconfsubtype):
|
|
||||||
typemap = { 'string': 's', 'int': 'i', 'float': 'f', 'bool': 'b', 'list': 'a' }
|
|
||||||
result = typemap[gconftype]
|
|
||||||
if gconftype == 'list':
|
|
||||||
result = result + typemap[gconfsubtype]
|
|
||||||
return result
|
|
||||||
|
|
||||||
|
|
||||||
class GConfSchema:
|
|
||||||
|
|
||||||
def __init__(self, node):
|
|
||||||
locale_node = node.find('locale')
|
|
||||||
|
|
||||||
self.key = node.find('key').text
|
|
||||||
self.type = node.find('type').text
|
|
||||||
if self.type == 'list':
|
|
||||||
self.list_type = node.find('list_type').text
|
|
||||||
else:
|
|
||||||
self.list_type = None
|
|
||||||
self.varianttype = map_gconf_type_to_variant_type(self.type, self.list_type)
|
|
||||||
|
|
||||||
applyto_node = node.find('applyto')
|
|
||||||
if applyto_node is not None:
|
|
||||||
self.applyto = node.find('applyto').text
|
|
||||||
self.applyto.strip()
|
|
||||||
self.keyname = self.applyto[self.applyto.rfind('/')+1:]
|
|
||||||
self.prefix = self.applyto[:self.applyto.rfind('/')+1]
|
|
||||||
else:
|
|
||||||
self.applyto = None
|
|
||||||
self.key.strip()
|
|
||||||
self.keyname = self.key[self.key.rfind('/')+1:]
|
|
||||||
self.prefix = self.key[:self.key.rfind('/')+1]
|
|
||||||
self.prefix = os.path.normpath(self.prefix)
|
|
||||||
|
|
||||||
try:
|
|
||||||
self.default = locale_node.find('default').text
|
|
||||||
self.localized = 'messages'
|
|
||||||
except:
|
|
||||||
try:
|
|
||||||
self.default = node.find('default').text
|
|
||||||
self.localized = None
|
|
||||||
except:
|
|
||||||
raise GSettingsSchemaConvertException('No default value for key \'%s\'. A default value is always required in GSettings schemas.' % self.applyto or self.key)
|
|
||||||
self.typed_default = None
|
|
||||||
|
|
||||||
self.short = self._get_value_with_locale(node, locale_node, 'short')
|
|
||||||
self.long = self._get_value_with_locale(node, locale_node, 'long')
|
|
||||||
|
|
||||||
self.short = self._oneline(self.short)
|
|
||||||
self.long = self._oneline(self.long)
|
|
||||||
|
|
||||||
# Fix the default to be parsable by GVariant
|
|
||||||
if self.type == 'string':
|
|
||||||
if not self.default:
|
|
||||||
self.default = '\'\''
|
|
||||||
else:
|
|
||||||
self.default.replace('\'', '\\\'')
|
|
||||||
self.default = '\'%s\'' % self.default
|
|
||||||
elif self.type == 'bool':
|
|
||||||
self.default = self.default.lower()
|
|
||||||
elif self.type == 'list':
|
|
||||||
l = self.default.strip()
|
|
||||||
if not (l[0] == '[' and l[-1] == ']'):
|
|
||||||
raise GSettingsSchemaConvertException('Cannot parse default list value \'%s\' for key \'%s\'.' % (self.default, self.applyto or self.key))
|
|
||||||
values = l[1:-1].strip()
|
|
||||||
if not values:
|
|
||||||
self.typed_default = '@%s []' % self.varianttype
|
|
||||||
elif self.list_type == 'string':
|
|
||||||
items = [ item.strip() for item in values.split(',') ]
|
|
||||||
items = [ item.replace('\'', '\\\'') for item in items ]
|
|
||||||
values = ', '.join([ '\'%s\'' % item for item in items ])
|
|
||||||
self.default = '[ %s ]' % values
|
|
||||||
|
|
||||||
def _get_value_with_locale(self, node, locale_node, element):
|
|
||||||
element_node = None
|
|
||||||
if locale_node is not None:
|
|
||||||
element_node = locale_node.find(element)
|
|
||||||
if element_node is None:
|
|
||||||
element_node = node.find(element)
|
|
||||||
if element_node is not None:
|
|
||||||
return element_node.text
|
|
||||||
else:
|
|
||||||
return None
|
|
||||||
|
|
||||||
def _oneline(self, s):
|
|
||||||
lines = s.splitlines()
|
|
||||||
result = ''
|
|
||||||
for line in lines:
|
|
||||||
result += ' ' + line.lstrip()
|
|
||||||
return result.strip()
|
|
||||||
|
|
||||||
def get_gsettings_schema_key(self):
|
|
||||||
key = GSettingsSchemaKey()
|
|
||||||
key.fill(self.keyname, self.varianttype, self.default, self.typed_default, self.localized, self.keyname, self.short, self.long, None, None)
|
|
||||||
return key
|
|
||||||
|
|
||||||
|
|
||||||
######################################
|
|
||||||
|
|
||||||
|
|
||||||
class SimpleSchemaParser:
|
class SimpleSchemaParser:
|
||||||
|
|
||||||
allowed_tokens = {
|
allowed_tokens = {
|
||||||
@ -733,82 +635,192 @@ class SimpleSchemaParser:
|
|||||||
######################################
|
######################################
|
||||||
|
|
||||||
|
|
||||||
def read_gconf_schema(gconf_schema_file, default_schema_id):
|
def map_gconf_type_to_variant_type(gconftype, gconfsubtype):
|
||||||
gsettings_schema_root = GSettingsSchemaRoot()
|
typemap = { 'string': 's', 'int': 'i', 'float': 'f', 'bool': 'b', 'list': 'a' }
|
||||||
|
result = typemap[gconftype]
|
||||||
|
if gconftype == 'list':
|
||||||
|
result = result + typemap[gconfsubtype]
|
||||||
|
return result
|
||||||
|
|
||||||
default_schema_id_count = 0
|
|
||||||
|
|
||||||
gconfschemafile_node = ET.parse(gconf_schema_file).getroot()
|
class GConfSchema:
|
||||||
for schemalist_node in gconfschemafile_node.findall('schemalist'):
|
|
||||||
for schema_node in schemalist_node.findall('schema'):
|
|
||||||
gconf_schema = GConfSchema(schema_node)
|
|
||||||
|
|
||||||
schemas_only = (gconf_schema.applyto is not None)
|
def __init__(self, node):
|
||||||
|
locale_node = node.find('locale')
|
||||||
|
|
||||||
dirpath = gconf_schema.prefix
|
self.key = node.find('key').text
|
||||||
if dirpath[0] != '/':
|
self.type = node.find('type').text
|
||||||
raise GSettingsSchemaConvertException('Key \'%s\' has a relative path. There is no relative path in GSettings schemas.' % gconf_schema.applyto or gconf_schema.key)
|
if self.type == 'list':
|
||||||
|
self.list_type = node.find('list_type').text
|
||||||
|
else:
|
||||||
|
self.list_type = None
|
||||||
|
self.varianttype = map_gconf_type_to_variant_type(self.type, self.list_type)
|
||||||
|
|
||||||
# remove leading 'schemas/' for schemas-only keys
|
applyto_node = node.find('applyto')
|
||||||
if schemas_only and dirpath.startswith('/schemas/'):
|
if applyto_node is not None:
|
||||||
dirpath = dirpath[len('/schemas'):]
|
self.applyto = node.find('applyto').text
|
||||||
|
self.applyto.strip()
|
||||||
|
self.keyname = self.applyto[self.applyto.rfind('/')+1:]
|
||||||
|
self.prefix = self.applyto[:self.applyto.rfind('/')+1]
|
||||||
|
else:
|
||||||
|
self.applyto = None
|
||||||
|
self.key.strip()
|
||||||
|
self.keyname = self.key[self.key.rfind('/')+1:]
|
||||||
|
self.prefix = self.key[:self.key.rfind('/')+1]
|
||||||
|
self.prefix = os.path.normpath(self.prefix)
|
||||||
|
|
||||||
if len(dirpath) == 1:
|
try:
|
||||||
raise GSettingsSchemaConvertException('Key \'%s\' is a toplevel key. Toplevel keys are not accepted in GSettings schemas.' % gconf_schema.applyto or gconf_schema.key)
|
self.default = locale_node.find('default').text
|
||||||
|
self.localized = 'messages'
|
||||||
|
except:
|
||||||
|
try:
|
||||||
|
self.default = node.find('default').text
|
||||||
|
self.localized = None
|
||||||
|
except:
|
||||||
|
raise GSettingsSchemaConvertException('No default value for key \'%s\'. A default value is always required in GSettings schemas.' % self.applyto or self.key)
|
||||||
|
self.typed_default = None
|
||||||
|
|
||||||
# remove trailing slash because we'll split the string
|
self.short = self._get_value_with_locale(node, locale_node, 'short')
|
||||||
if dirpath[-1] == '/':
|
self.long = self._get_value_with_locale(node, locale_node, 'long')
|
||||||
dirpath = dirpath[:-1]
|
|
||||||
# and also remove leading slash when splitting
|
|
||||||
hierarchy = dirpath[1:].split('/')
|
|
||||||
|
|
||||||
# we don't want to put apps/ and desktop/ keys in the same schema,
|
self.short = self._oneline(self.short)
|
||||||
# so we have a first step where we make sure to create a new schema
|
self.long = self._oneline(self.long)
|
||||||
# to avoid this case if necessary
|
|
||||||
gsettings_schema = None
|
# Fix the default to be parsable by GVariant
|
||||||
for schema in gsettings_schema_root.schemas:
|
if self.type == 'string':
|
||||||
if schemas_only:
|
if not self.default:
|
||||||
schema_path = schema.path
|
self.default = '\'\''
|
||||||
else:
|
else:
|
||||||
schema_path = schema._hacky_path
|
self.default.replace('\'', '\\\'')
|
||||||
if dirpath.startswith(schema_path):
|
self.default = '\'%s\'' % self.default
|
||||||
gsettings_schema = schema
|
elif self.type == 'bool':
|
||||||
|
self.default = self.default.lower()
|
||||||
|
elif self.type == 'list':
|
||||||
|
l = self.default.strip()
|
||||||
|
if not (l[0] == '[' and l[-1] == ']'):
|
||||||
|
raise GSettingsSchemaConvertException('Cannot parse default list value \'%s\' for key \'%s\'.' % (self.default, self.applyto or self.key))
|
||||||
|
values = l[1:-1].strip()
|
||||||
|
if not values:
|
||||||
|
self.typed_default = '@%s []' % self.varianttype
|
||||||
|
elif self.list_type == 'string':
|
||||||
|
items = [ item.strip() for item in values.split(',') ]
|
||||||
|
items = [ item.replace('\'', '\\\'') for item in items ]
|
||||||
|
values = ', '.join([ '\'%s\'' % item for item in items ])
|
||||||
|
self.default = '[ %s ]' % values
|
||||||
|
|
||||||
|
def _get_value_with_locale(self, node, locale_node, element):
|
||||||
|
element_node = None
|
||||||
|
if locale_node is not None:
|
||||||
|
element_node = locale_node.find(element)
|
||||||
|
if element_node is None:
|
||||||
|
element_node = node.find(element)
|
||||||
|
if element_node is not None:
|
||||||
|
return element_node.text
|
||||||
|
else:
|
||||||
|
return None
|
||||||
|
|
||||||
|
def _oneline(self, s):
|
||||||
|
lines = s.splitlines()
|
||||||
|
result = ''
|
||||||
|
for line in lines:
|
||||||
|
result += ' ' + line.lstrip()
|
||||||
|
return result.strip()
|
||||||
|
|
||||||
|
def get_gsettings_schema_key(self):
|
||||||
|
key = GSettingsSchemaKey()
|
||||||
|
key.fill(self.keyname, self.varianttype, self.default, self.typed_default, self.localized, self.keyname, self.short, self.long, None, None)
|
||||||
|
return key
|
||||||
|
|
||||||
|
|
||||||
|
######################################
|
||||||
|
|
||||||
|
|
||||||
|
class GConfSchemaParser:
|
||||||
|
|
||||||
|
def __init__(self, file, default_schema_id):
|
||||||
|
self.file = file
|
||||||
|
self.default_schema_id = default_schema_id
|
||||||
|
|
||||||
|
self.root = None
|
||||||
|
self.default_schema_id_count = 0
|
||||||
|
|
||||||
|
def _insert_schema(self, gconf_schema):
|
||||||
|
schemas_only = (gconf_schema.applyto is not None)
|
||||||
|
|
||||||
|
dirpath = gconf_schema.prefix
|
||||||
|
if dirpath[0] != '/':
|
||||||
|
raise GSettingsSchemaConvertException('Key \'%s\' has a relative path. There is no relative path in GSettings schemas.' % gconf_schema.applyto or gconf_schema.key)
|
||||||
|
|
||||||
|
# remove leading 'schemas/' for schemas-only keys
|
||||||
|
if schemas_only and dirpath.startswith('/schemas/'):
|
||||||
|
dirpath = dirpath[len('/schemas'):]
|
||||||
|
|
||||||
|
if len(dirpath) == 1:
|
||||||
|
raise GSettingsSchemaConvertException('Key \'%s\' is a toplevel key. Toplevel keys are not accepted in GSettings schemas.' % gconf_schema.applyto or gconf_schema.key)
|
||||||
|
|
||||||
|
# remove trailing slash because we'll split the string
|
||||||
|
if dirpath[-1] == '/':
|
||||||
|
dirpath = dirpath[:-1]
|
||||||
|
# and also remove leading slash when splitting
|
||||||
|
hierarchy = dirpath[1:].split('/')
|
||||||
|
|
||||||
|
# we don't want to put apps/ and desktop/ keys in the same schema,
|
||||||
|
# so we have a first step where we make sure to create a new schema
|
||||||
|
# to avoid this case if necessary
|
||||||
|
gsettings_schema = None
|
||||||
|
for schema in self.root.schemas:
|
||||||
|
if schemas_only:
|
||||||
|
schema_path = schema.path
|
||||||
|
else:
|
||||||
|
schema_path = schema._hacky_path
|
||||||
|
if dirpath.startswith(schema_path):
|
||||||
|
gsettings_schema = schema
|
||||||
|
break
|
||||||
|
if not gsettings_schema:
|
||||||
|
gsettings_schema = GSettingsSchema()
|
||||||
|
if self.default_schema_id:
|
||||||
|
gsettings_schema.id = self.default_schema_id
|
||||||
|
if self.default_schema_id_count > 0:
|
||||||
|
gsettings_schema.id += '.FIXME-%s' % self.default_schema_id_count
|
||||||
|
self.default_schema_id_count += 1
|
||||||
|
else:
|
||||||
|
gsettings_schema.id = 'FIXME'
|
||||||
|
if schemas_only:
|
||||||
|
gsettings_schema.path = '/' + hierarchy[0] + '/'
|
||||||
|
else:
|
||||||
|
gsettings_schema._hacky_path = '/' + hierarchy[0] + '/'
|
||||||
|
self.root.schemas.append(gsettings_schema)
|
||||||
|
|
||||||
|
# we create all the subdirs that lead to this key
|
||||||
|
gsettings_dir = gsettings_schema
|
||||||
|
for item in hierarchy[1:]:
|
||||||
|
subdir = None
|
||||||
|
for dir in gsettings_dir.dirs:
|
||||||
|
if dir.name == item:
|
||||||
|
subdir = dir
|
||||||
break
|
break
|
||||||
if not gsettings_schema:
|
if not subdir:
|
||||||
gsettings_schema = GSettingsSchema()
|
subdir = GSettingsSchemaDir()
|
||||||
if default_schema_id:
|
subdir.name = item
|
||||||
gsettings_schema.id = default_schema_id
|
gsettings_dir.dirs.append(subdir)
|
||||||
if default_schema_id_count > 0:
|
gsettings_dir = subdir
|
||||||
gsettings_schema.id += '.FIXME-%s' % default_schema_id_count
|
|
||||||
default_schema_id_count += 1
|
|
||||||
else:
|
|
||||||
gsettings_schema.id = 'FIXME'
|
|
||||||
if schemas_only:
|
|
||||||
gsettings_schema.path = '/' + hierarchy[0] + '/'
|
|
||||||
else:
|
|
||||||
gsettings_schema._hacky_path = '/' + hierarchy[0] + '/'
|
|
||||||
gsettings_schema_root.schemas.append(gsettings_schema)
|
|
||||||
|
|
||||||
# we create all the subdirs that lead to this key
|
# we have the final directory, so we can put the key there
|
||||||
gsettings_dir = gsettings_schema
|
gsettings_dir.keys.append(gconf_schema.get_gsettings_schema_key())
|
||||||
for item in hierarchy[1:]:
|
|
||||||
subdir = None
|
|
||||||
for dir in gsettings_dir.dirs:
|
|
||||||
if dir.name == item:
|
|
||||||
subdir = dir
|
|
||||||
break
|
|
||||||
if not subdir:
|
|
||||||
subdir = GSettingsSchemaDir()
|
|
||||||
subdir.name = item
|
|
||||||
gsettings_dir.dirs.append(subdir)
|
|
||||||
gsettings_dir = subdir
|
|
||||||
|
|
||||||
# we have the final directory, so we can put the key there
|
def parse(self):
|
||||||
gsettings_dir.keys.append(gconf_schema.get_gsettings_schema_key())
|
# reset the state of the parser
|
||||||
|
self.root = GSettingsSchemaRoot()
|
||||||
|
self.default_schema_id_count = 0
|
||||||
|
|
||||||
gsettings_schema_root.simplify()
|
gconfschemafile_node = ET.parse(self.file).getroot()
|
||||||
|
for schemalist_node in gconfschemafile_node.findall('schemalist'):
|
||||||
|
for schema_node in schemalist_node.findall('schema'):
|
||||||
|
self._insert_schema(GConfSchema(schema_node))
|
||||||
|
|
||||||
return gsettings_schema_root
|
self.root.simplify()
|
||||||
|
|
||||||
|
return self.root
|
||||||
|
|
||||||
|
|
||||||
######################################
|
######################################
|
||||||
@ -866,7 +878,8 @@ def main(args):
|
|||||||
|
|
||||||
if options.gconf:
|
if options.gconf:
|
||||||
try:
|
try:
|
||||||
schema_root = read_gconf_schema(argfile, options.schema_id)
|
parser = GConfSchemaParser(argfile, options.schema_id)
|
||||||
|
schema_root = parser.parse()
|
||||||
except SyntaxError, e:
|
except SyntaxError, e:
|
||||||
raise GSettingsSchemaConvertException('\'%s\' does not look like a valid gconf schema file: %s' % (argfile, e))
|
raise GSettingsSchemaConvertException('\'%s\' does not look like a valid gconf schema file: %s' % (argfile, e))
|
||||||
else:
|
else:
|
||||||
|
Loading…
x
Reference in New Issue
Block a user