[glib/new-gsettings] Add xml schema parser to converter
- From: Vincent Untz <vuntz src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [glib/new-gsettings] Add xml schema parser to converter
- Date: Sat, 17 Apr 2010 21:56:26 +0000 (UTC)
commit 15c28d90fbcadf13d1e18db1883455c60a83c155
Author: Vincent Untz <vuntz gnome org>
Date: Sat Apr 17 17:54:46 2010 -0400
Add xml schema parser to converter
This makes it possible to easily move an XML schema to the simple
format if wanted.
Also fix a small issue when outputting a range in the simple format.
gio/gsettings-schema-convert | 163 +++++++++++++++++++++++++++++++++++++++--
1 files changed, 155 insertions(+), 8 deletions(-)
---
diff --git a/gio/gsettings-schema-convert b/gio/gsettings-schema-convert
index 54c15e9..3c9e96f 100755
--- a/gio/gsettings-schema-convert
+++ b/gio/gsettings-schema-convert
@@ -311,7 +311,7 @@ class GSettingsSchemaKey:
if self._has_range_choices():
result += '%schoices: %s\n' % (current_indent, ', '.join(self.choices))
elif self._has_range_minmax():
- result += '%srange: %s\n' % (current_indent, '%s..%s' % self.range)
+ result += '%srange: %s\n' % (current_indent, '%s..%s' % (self.range[0] or '', self.range[1] or ''))
return result
def get_xml_node(self):
@@ -635,6 +635,146 @@ class SimpleSchemaParser:
######################################
+class XMLSchemaParser:
+
+ def __init__(self, file):
+ self.file = file
+
+ self.root = None
+
+ def _parse_key(self, key_node, schema):
+ key = GSettingsSchemaKey()
+
+ key.name = key_node.get('name')
+ if not key.name:
+ raise GSettingsSchemaConvertException('A key in schema \'%s\' has no name.' % schema.id)
+ key.type = key_node.get('type')
+ if not key.type:
+ raise GSettingsSchemaConvertException('Key \'%s\' in schema \'%s\' has no type.' % (key.name, schema.id))
+
+ default_node = key_node.find('default')
+ if default_node is None or not default_node.text.strip():
+ raise GSettingsSchemaConvertException('Key \'%s\' in schema \'%s\' has no default value.' % (key.name, schema.id))
+ key.l10n = default_node.get('l10n')
+ key.l10n_context = default_node.get('context')
+ key.default = default_node.text.strip()
+
+ summary_node = key_node.find('summary')
+ if summary_node is not None:
+ key.summary = summary_node.text.strip()
+ description_node = key_node.find('description')
+ if description_node is not None:
+ key.description = description_node.text.strip()
+
+ range_node = key_node.find('range')
+ if range_node is not None:
+ min = None
+ max = None
+ min_node = range_node.find('min')
+ if min_node is not None:
+ min = min_node.text.strip()
+ max_node = range_node.find('max')
+ if max_node is not None:
+ max = max_node.text.strip()
+ if min or max:
+ self.range = (min, max)
+
+ choices_node = key_node.find('choices')
+ if choices_node is not None:
+ self.choices = []
+ for choice_node in choices_node.findall('choice'):
+ value = choice_node.get('value')
+ if value:
+ self.choices.append(value)
+ else:
+ raise GSettingsSchemaConvertException('A choice for key \'%s\' in schema \'%s\' has no value.' % (key.name, schema.id))
+
+ return key
+
+ def _parse_schema(self, schema_node):
+ schema = GSettingsSchema()
+
+ schema._children = []
+
+ schema.id = schema_node.get('id')
+ if not schema.id:
+ raise GSettingsSchemaConvertException('A schema has no id.')
+ schema.path = schema_node.get('path')
+ schema.gettext_domain = schema_node.get('gettext-domain')
+
+ for key_node in schema_node.findall('key'):
+ key = self._parse_key(key_node, schema)
+ schema.keys.append(key)
+
+ for child_node in schema_node.findall('child'):
+ child_name = child_node.get('name')
+ if not child_name:
+ raise GSettingsSchemaConvertException('A child of schema \'%s\' has no name.' % schema.id)
+ child_schema = child_node.get('schema')
+ if not child_schema:
+ raise GSettingsSchemaConvertException('Child \'%s\' of schema \'%s\' has no schema.' % (child_name, schema.id))
+
+ expected_id = schema.id + '.' + child_name
+ if child_schema != expected_id:
+ raise GSettingsSchemaConvertException('\'%s\' is too complex for this tool: child \'%s\' of schema \'%s\' has a schema that is not the expected one (\'%s\' vs \'%s\').' % (os.path.basename(self.file), child_name, schema.id, child_schema, expected_id))
+
+ schema._children.append((child_schema, child_name))
+
+ return schema
+
+ def parse(self):
+ self.root = GSettingsSchemaRoot()
+ schemas = []
+ parent = {}
+
+ schemalist_node = ET.parse(self.file).getroot()
+ self.root.gettext_domain = schemalist_node.get('gettext-domain')
+
+ for schema_node in schemalist_node.findall('schema'):
+ schema = self._parse_schema(schema_node)
+
+ for (child_schema, child_name) in schema._children:
+ if parent.has_key(child_schema):
+ raise GSettingsSchemaConvertException('Child \'%s\' is declared by two different schemas: \'%s\' and \'%s\'.' % (child_schema, parent[child_schema], schema.id))
+ parent[child_schema] = schema
+
+ schemas.append(schema)
+
+ # now let's move all schemas where they should leave
+ for schema in schemas:
+ if parent.has_key(schema.id):
+ parent_schema = parent[schema.id]
+
+ # check that the paths of parent and child are supported by
+ # this tool
+ found = False
+ for (child_schema, child_name) in parent_schema._children:
+ if child_schema == schema.id:
+ found = True
+ expected_path = parent_schema.path + child_name + '/'
+ if schema.path != expected_path:
+ raise GSettingsSchemaConvertException('\'%s\' is too complex for this tool: child \'%s\' of schema \'%s\' has a path that is not the expected one (\'%s\' vs \'%s\').' % (os.path.basename(self.file), child_name, parent_schema.id, schema.path, expected_path))
+ break
+
+ if not found:
+ raise GSettingsSchemaConvertException('Internal error: child not found in parent\'s children.')
+
+ schema_dir = GSettingsSchemaDir()
+ schema_dir.name = child_name
+ schema_dir.gettext_domain = schema.gettext_domain
+ schema_dir.dirs = schema.dirs
+ schema_dir.keys = schema.keys
+
+ parent_schema.dirs.append(schema_dir)
+ else:
+ self.root.schemas.append(schema)
+
+ return self.root
+
+
+######################################
+
+
def map_gconf_type_to_variant_type(gconftype, gconfsubtype):
typemap = { 'string': 's', 'int': 'i', 'float': 'f', 'bool': 'b', 'list': 'a' }
result = typemap[gconftype]
@@ -854,11 +994,6 @@ def main(args):
if options.simple and options.xml:
print >> sys.stderr, 'Too many output formats requested.'
return 1
- if not options.simple and not options.xml:
- if options.gconf:
- options.simple = True
- else:
- options.xml = True
if not options.gconf and options.schema_id:
print >> sys.stderr, 'Default schema ID can only be specified when converting a gconf schema.'
@@ -877,14 +1012,26 @@ def main(args):
raise GSettingsSchemaConvertException('\'%s\' already exists. Use --force to overwrite it.' % options.output)
if options.gconf:
+ if not options.simple and not options.xml:
+ options.simple = True
+
try:
parser = GConfSchemaParser(argfile, options.schema_id)
schema_root = parser.parse()
except SyntaxError, e:
raise GSettingsSchemaConvertException('\'%s\' does not look like a valid gconf schema file: %s' % (argfile, e))
else:
- parser = SimpleSchemaParser(argfile)
- schema_root = parser.parse()
+ # autodetect if file is XML or not
+ try:
+ parser = XMLSchemaParser(argfile)
+ schema_root = parser.parse()
+ if not options.simple and not options.xml:
+ options.simple = True
+ except SyntaxError, e:
+ parser = SimpleSchemaParser(argfile)
+ schema_root = parser.parse()
+ if not options.simple and not options.xml:
+ options.xml = True
if options.xml:
node = schema_root.get_xml_node()
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]