mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2025-02-24 11:12:11 +01:00
Add gsettings-schema-convert script
It can be used to convert a gconf schema to either a simple gsettings schema format or the full xml gsettings schema format. It also converts from the simple format to the full xml format.
This commit is contained in:
parent
66bc7ced39
commit
975cf8a3b3
673
gio/gsettings-schema-convert
Normal file
673
gio/gsettings-schema-convert
Normal file
@ -0,0 +1,673 @@
|
||||
#!/usr/bin/env python
|
||||
# vim: set ts=4 sw=4 et: coding=UTF-8
|
||||
#
|
||||
# Copyright (c) 2010, Novell, Inc.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU Lesser General Public License
|
||||
# as published by the Free Software Foundation; either version 2
|
||||
# of the License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public
|
||||
# License along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
|
||||
# USA.
|
||||
#
|
||||
# Authors: Vincent Untz <vuntz@gnome.org>
|
||||
|
||||
import os
|
||||
import sys
|
||||
|
||||
import optparse
|
||||
|
||||
try:
|
||||
from lxml import etree as ET
|
||||
except ImportError:
|
||||
try:
|
||||
from xml.etree import cElementTree as ET
|
||||
except ImportError:
|
||||
import cElementTree as ET
|
||||
|
||||
|
||||
GSETTINGS_SIMPLE_SCHEMA_INDENT = ' '
|
||||
|
||||
|
||||
######################################
|
||||
|
||||
|
||||
class GSettingsSchemaConvertException(Exception):
|
||||
pass
|
||||
|
||||
|
||||
######################################
|
||||
|
||||
|
||||
class GSettingsSchemaRoot:
|
||||
|
||||
def __init__(self):
|
||||
self.schemas = []
|
||||
|
||||
def simplify(self):
|
||||
for schema in self.schemas:
|
||||
schema.simplify()
|
||||
|
||||
def get_simple_string(self):
|
||||
need_empty_line = False
|
||||
result = ''
|
||||
|
||||
for schema in self.schemas:
|
||||
if need_empty_line:
|
||||
result += '\n'
|
||||
result += schema.get_simple_string()
|
||||
if result:
|
||||
need_empty_line = True
|
||||
|
||||
return result
|
||||
|
||||
def get_xml_node(self):
|
||||
schemalist_node = ET.Element('schemalist')
|
||||
for schema in self.schemas:
|
||||
schema_node = schema.get_xml_node()
|
||||
if schema_node is not None:
|
||||
schemalist_node.append(schema_node)
|
||||
return schemalist_node
|
||||
|
||||
|
||||
######################################
|
||||
|
||||
|
||||
# Note: defined before GSettingsSchema because GSettingsSchema is a subclass.
|
||||
# But from a schema point of view, GSettingsSchema is a parent of
|
||||
# GSettingsSchemaDir.
|
||||
class GSettingsSchemaDir:
|
||||
|
||||
def __init__(self):
|
||||
self.name = None
|
||||
self.dirs = []
|
||||
self.keys = []
|
||||
|
||||
def get_simple_string(self, current_indent):
|
||||
content = self._get_simple_string_for_content(current_indent)
|
||||
if not content:
|
||||
return ''
|
||||
|
||||
result = ''
|
||||
result += '%schild %s:\n' % (current_indent, self.name)
|
||||
result += content
|
||||
return result
|
||||
|
||||
def _get_simple_string_for_content(self, current_indent):
|
||||
need_empty_line = False
|
||||
result = ''
|
||||
|
||||
for key in self.keys:
|
||||
result += key.get_simple_string(current_indent + GSETTINGS_SIMPLE_SCHEMA_INDENT)
|
||||
need_empty_line = True
|
||||
|
||||
for dir in self.dirs:
|
||||
if need_empty_line:
|
||||
result += '\n'
|
||||
result += dir.get_simple_string(current_indent + GSETTINGS_SIMPLE_SCHEMA_INDENT)
|
||||
if result:
|
||||
need_empty_line = True
|
||||
|
||||
return result
|
||||
|
||||
def get_xml_node(self):
|
||||
node = self._get_xml_node_for_content()
|
||||
if node is not None:
|
||||
node.set('id', self.name)
|
||||
return node
|
||||
|
||||
def _get_xml_node_for_content(self):
|
||||
if not self.keys and not self.dirs:
|
||||
return None
|
||||
|
||||
schema_node = ET.Element('schema')
|
||||
for key in self.keys:
|
||||
key_node = key.get_xml_node()
|
||||
schema_node.append(key_node)
|
||||
for dir in self.dirs:
|
||||
dir_node = dir.get_xml_node()
|
||||
schema_node.append(dir_node)
|
||||
|
||||
return schema_node
|
||||
|
||||
|
||||
######################################
|
||||
|
||||
|
||||
class GSettingsSchema(GSettingsSchemaDir):
|
||||
|
||||
def __init__(self):
|
||||
self.id = None
|
||||
self.path = None
|
||||
self.dirs = []
|
||||
self.keys = []
|
||||
|
||||
def simplify(self):
|
||||
while len(self.dirs) == 1 and not self.keys:
|
||||
dir = self.dirs[0]
|
||||
self.dirs = dir.dirs
|
||||
self.keys = dir.keys
|
||||
if self.path:
|
||||
self.path += dir.name + '/'
|
||||
|
||||
def get_simple_string(self):
|
||||
if not self.dirs and not self.keys:
|
||||
return ''
|
||||
|
||||
result = ''
|
||||
result += 'schema %s:\n' % self.id
|
||||
if self.path:
|
||||
result += '%spath %s\n' % (GSETTINGS_SIMPLE_SCHEMA_INDENT, self.path)
|
||||
result += '\n'
|
||||
result += self._get_simple_string_for_content('')
|
||||
|
||||
return result
|
||||
|
||||
def get_xml_node(self):
|
||||
if not self.dirs and not self.keys:
|
||||
return None
|
||||
|
||||
node = self._get_xml_node_for_content()
|
||||
node.set('id', self.id)
|
||||
if self.path:
|
||||
node.set('path', self.path)
|
||||
|
||||
return node
|
||||
|
||||
|
||||
######################################
|
||||
|
||||
|
||||
class GSettingsSchemaKey:
|
||||
|
||||
def __init__(self):
|
||||
self.name = None
|
||||
self.type = None
|
||||
self.default = None
|
||||
self.typed_default = None
|
||||
self.localized = None
|
||||
self.summary = None
|
||||
self.description = None
|
||||
|
||||
def fill(self, name, type, default, typed_default, localized, summary, description):
|
||||
self.name = name
|
||||
self.type = type
|
||||
self.default = default
|
||||
self.typed_default = typed_default
|
||||
self.localized = localized
|
||||
self.summary = summary
|
||||
self.description = description
|
||||
|
||||
def get_simple_string(self, current_indent):
|
||||
result = ''
|
||||
result += '%skey %s = %s\n' % (current_indent, self.name, self.typed_default or self.default)
|
||||
current_indent += GSETTINGS_SIMPLE_SCHEMA_INDENT
|
||||
if self.summary:
|
||||
result += '%sSummary: %s\n' % (current_indent, self.summary)
|
||||
if self.description:
|
||||
result += '%sDescription: %s\n' % (current_indent, self.description)
|
||||
return result
|
||||
|
||||
def get_xml_node(self):
|
||||
key_node = ET.Element('key')
|
||||
key_node.set('name', self.name)
|
||||
key_node.set('type', self.type)
|
||||
default_node = ET.SubElement(key_node, 'default')
|
||||
default_node.text = self.default
|
||||
if self.summary:
|
||||
summary_node = ET.SubElement(key_node, 'summary')
|
||||
summary_node.text = self.summary
|
||||
if self.description:
|
||||
description_node = ET.SubElement(key_node, 'description')
|
||||
description_node.text = self.description
|
||||
return key_node
|
||||
|
||||
|
||||
######################################
|
||||
|
||||
|
||||
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 = True
|
||||
except:
|
||||
self.default = node.find('default').text
|
||||
self.localized = False
|
||||
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 value for list: %s' % self.default)
|
||||
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
|
||||
|
||||
# FIXME: kill this when we'll have python bindings for GVariant. Right
|
||||
# now, every simple format schema we'll generate has to have an
|
||||
# explicit type since we can't guess the type later on when converting
|
||||
# to XML.
|
||||
if not self.typed_default:
|
||||
self.typed_default = '@%s %s' % (self.varianttype, self.default)
|
||||
|
||||
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.short, self.long)
|
||||
return key
|
||||
|
||||
|
||||
######################################
|
||||
|
||||
allowed_tokens = {
|
||||
'' : [ 'schema' ],
|
||||
'schema' : [ 'path', 'child', 'key' ],
|
||||
'path' : [ ],
|
||||
'child' : [ 'child', 'key' ],
|
||||
'key' : [ 'summary', 'description' ],
|
||||
'summary' : [ ],
|
||||
'description' : [ ]
|
||||
}
|
||||
|
||||
def _eat_indent(line, indent_stack):
|
||||
i = 0
|
||||
buf = ''
|
||||
previous_max_index = len(indent_stack) - 1
|
||||
index = -1
|
||||
|
||||
while i < len(line) - 1 and line[i].isspace():
|
||||
buf += line[i]
|
||||
i += 1
|
||||
if previous_max_index > index:
|
||||
if buf == indent_stack[index + 1]:
|
||||
buf = ''
|
||||
index += 1
|
||||
continue
|
||||
elif indent_stack[index + 1].startswith(buf):
|
||||
continue
|
||||
else:
|
||||
raise GSettingsSchemaConvertException('Indentation not consistent.')
|
||||
else:
|
||||
continue
|
||||
|
||||
if buf and previous_max_index <= index:
|
||||
indent_stack.append(buf)
|
||||
elif previous_max_index > index:
|
||||
indent_stack = indent_stack[:index + 1]
|
||||
|
||||
return (indent_stack, line[i:])
|
||||
|
||||
def _eat_word(line):
|
||||
i = 0
|
||||
while i < len(line) - 1 and not line[i].isspace():
|
||||
i += 1
|
||||
return (line[:i], line[i:])
|
||||
|
||||
def _word_to_token(word):
|
||||
if word == 'schema':
|
||||
return 'schema'
|
||||
if word == 'path':
|
||||
return 'path'
|
||||
if word == 'child':
|
||||
return 'child'
|
||||
if word == 'key':
|
||||
return 'key'
|
||||
if word == 'Summary:':
|
||||
return 'summary'
|
||||
if word == 'Description:':
|
||||
return 'description'
|
||||
raise GSettingsSchemaConvertException('\'%s\' is not a valid token.' % word)
|
||||
|
||||
def _get_name_without_colon(line):
|
||||
if line[-1] != ':':
|
||||
raise GSettingsSchemaConvertException('\'%s\' has no trailing colon.' % line)
|
||||
line = line[:-1].strip()
|
||||
# FIXME: we could check there's no space
|
||||
return line
|
||||
|
||||
def _parse_key(line):
|
||||
items = line.split('=')
|
||||
if len(items) != 2:
|
||||
raise GSettingsSchemaConvertException('Cannot parse key \'%s\'.' % line)
|
||||
name = items[0].strip()
|
||||
type = ''
|
||||
value = items[1].strip()
|
||||
if value[0] == '@':
|
||||
i = 1
|
||||
while not value[i].isspace():
|
||||
i += 1
|
||||
type = value[1:i]
|
||||
value = value[i:].strip()
|
||||
if not value:
|
||||
raise GSettingsSchemaConvertException('No value specified for key \'%s\'.' % line)
|
||||
return (name, type, value)
|
||||
|
||||
def read_simple_schema(simple_schema_file):
|
||||
root = GSettingsSchemaRoot()
|
||||
|
||||
f = open(simple_schema_file, 'r')
|
||||
lines = f.readlines()
|
||||
f.close()
|
||||
lines = [ line[:-1] for line in lines ]
|
||||
|
||||
leading_indent = None
|
||||
indent_stack = []
|
||||
token_stack = []
|
||||
object_stack = [ root ]
|
||||
|
||||
for line in lines:
|
||||
# make sure that lines with only spaces are ignored and considered as
|
||||
# empty lines
|
||||
line = line.rstrip()
|
||||
|
||||
# ignore empty line
|
||||
if not line:
|
||||
continue
|
||||
|
||||
# look at the indentation to know where we should be
|
||||
(indent_stack, line) = _eat_indent(line, indent_stack)
|
||||
if leading_indent is None:
|
||||
leading_indent = len(indent_stack)
|
||||
|
||||
# ignore comments
|
||||
if line[0] == '#':
|
||||
continue
|
||||
|
||||
(word, line) = _eat_word(line)
|
||||
token = _word_to_token(word)
|
||||
line = line.lstrip()
|
||||
|
||||
new_level = len(indent_stack) - leading_indent
|
||||
old_level = len(token_stack)
|
||||
|
||||
if new_level > old_level + 1:
|
||||
raise GSettingsSchemaConvertException('Internal error: stacks not in sync.')
|
||||
elif new_level <= old_level:
|
||||
token_stack = token_stack[:new_level]
|
||||
# we always have the root
|
||||
object_stack = object_stack[:new_level + 1]
|
||||
|
||||
if new_level == 0:
|
||||
parent_token = ''
|
||||
else:
|
||||
parent_token = token_stack[-1]
|
||||
|
||||
if not token in allowed_tokens[parent_token]:
|
||||
raise GSettingsSchemaConvertException('Token \'%s\' not allowed after token \'%s\'.' % (token, parent_token))
|
||||
|
||||
current_object = object_stack[-1]
|
||||
|
||||
new_object = None
|
||||
if token == 'schema':
|
||||
name = _get_name_without_colon(line)
|
||||
new_object = GSettingsSchema()
|
||||
new_object.id = name
|
||||
current_object.schemas.append(new_object)
|
||||
elif token == 'path':
|
||||
current_object.path = line
|
||||
elif token == 'child':
|
||||
name = _get_name_without_colon(line)
|
||||
new_object = GSettingsSchemaDir()
|
||||
new_object.name = name
|
||||
current_object.dirs.append(new_object)
|
||||
elif token == 'key':
|
||||
new_object = GSettingsSchemaKey()
|
||||
(name, type, value) = _parse_key(line)
|
||||
new_object.name = name
|
||||
new_object.type = type
|
||||
new_object.default = value
|
||||
current_object.keys.append(new_object)
|
||||
elif token == 'summary':
|
||||
current_object.summary = line
|
||||
elif token == 'description':
|
||||
current_object.description = line
|
||||
|
||||
if new_object:
|
||||
token_stack.append(token)
|
||||
object_stack.append(new_object)
|
||||
|
||||
return root
|
||||
|
||||
|
||||
######################################
|
||||
|
||||
|
||||
def read_gconf_schema(gconf_schema_file):
|
||||
gsettings_schema_root = GSettingsSchemaRoot()
|
||||
|
||||
gconfschemafile_node = ET.parse(gconf_schema_file).getroot()
|
||||
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)
|
||||
|
||||
dirpath = gconf_schema.prefix
|
||||
# remove leading slash because there's none in gsettings, and trailing
|
||||
# slash because we'll split the string
|
||||
if dirpath[0] == '/':
|
||||
dirpath = dirpath[1:]
|
||||
if dirpath[-1] == '/':
|
||||
dirpath = dirpath[:-1]
|
||||
# remove leading 'schemas/' for schemas-only keys
|
||||
if schemas_only and dirpath.startswith('schemas/'):
|
||||
dirpath = dirpath[len('schemas/'):]
|
||||
|
||||
if not dirpath:
|
||||
raise GSettingsSchemaConvertException('Toplevel keys are not accepted: %s' % gconf_schema.applyto)
|
||||
|
||||
hierarchy = dirpath.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 gsettings_schema_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()
|
||||
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
|
||||
gsettings_dir = gsettings_schema
|
||||
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
|
||||
gsettings_dir.keys.append(gconf_schema.get_gsettings_schema_key())
|
||||
|
||||
gsettings_schema_root.simplify()
|
||||
|
||||
return gsettings_schema_root
|
||||
|
||||
|
||||
######################################
|
||||
|
||||
|
||||
def main(args):
|
||||
parser = optparse.OptionParser()
|
||||
|
||||
parser.add_option("-o", "--output", dest="output",
|
||||
help="output file")
|
||||
parser.add_option("-g", "--gconf", action="store_true", dest="gconf",
|
||||
default=False, help="convert a gconf schema file")
|
||||
parser.add_option("-s", "--simple", action="store_true", dest="simple",
|
||||
default=False, help="use the simple schema format as output (only for gconf schema conversion)")
|
||||
parser.add_option("-x", "--xml", action="store_true", dest="xml",
|
||||
default=False, help="use the xml schema format as output")
|
||||
parser.add_option("-f", "--force", action="store_true", dest="force",
|
||||
default=False, help="overwrite output file if already existing")
|
||||
|
||||
(options, args) = parser.parse_args()
|
||||
|
||||
if len(args) < 1:
|
||||
print >> sys.stderr, 'Need a filename to work on.'
|
||||
return 1
|
||||
elif len(args) > 1:
|
||||
print >> sys.stderr, 'Too many arguments.'
|
||||
return 1
|
||||
|
||||
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
|
||||
|
||||
argfile = os.path.expanduser(args[0])
|
||||
if not os.path.exists(argfile):
|
||||
print >> sys.stderr, '%s does not exist.' % argfile
|
||||
return 1
|
||||
|
||||
if options.output:
|
||||
options.output = os.path.expanduser(options.output)
|
||||
|
||||
try:
|
||||
if options.output and not options.force and os.path.exists(options.output):
|
||||
raise GSettingsSchemaConvertException('%s already exists.' % options.output)
|
||||
|
||||
if options.gconf:
|
||||
try:
|
||||
schema_root = read_gconf_schema(argfile)
|
||||
except SyntaxError, e:
|
||||
raise GSettingsSchemaConvertException('%s does not look like a gconf schema file: %s' % (argfile, e))
|
||||
else:
|
||||
schema_root = read_simple_schema(argfile)
|
||||
|
||||
if options.xml:
|
||||
node = schema_root.get_xml_node()
|
||||
tree = ET.ElementTree(node)
|
||||
try:
|
||||
output = ET.tostring(tree, pretty_print = True)
|
||||
except TypeError:
|
||||
# pretty_print only works with lxml
|
||||
output = ET.tostring(tree)
|
||||
else:
|
||||
output = schema_root.get_simple_string()
|
||||
|
||||
if not options.output:
|
||||
sys.stdout.write(output)
|
||||
else:
|
||||
try:
|
||||
fout = open(options.output, 'w')
|
||||
fout.write(output)
|
||||
fout.close()
|
||||
except GSettingsSchemaConvertException, e:
|
||||
fout.close()
|
||||
if os.path.exists(options.output):
|
||||
os.unlink(options.output)
|
||||
raise e
|
||||
|
||||
except GSettingsSchemaConvertException, e:
|
||||
print >> sys.stderr, '%s' % e
|
||||
return 1
|
||||
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
try:
|
||||
res = main(sys.argv)
|
||||
sys.exit(res)
|
||||
except KeyboardInterrupt:
|
||||
pass
|
Loading…
x
Reference in New Issue
Block a user