2011-04-27 10:05:43 +00:00
|
|
|
#!/usr/bin/env python
|
|
|
|
#############################################################################
|
|
|
|
##
|
2012-01-05 04:03:39 +00:00
|
|
|
## Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
|
2011-04-27 10:05:43 +00:00
|
|
|
## All rights reserved.
|
|
|
|
## Contact: Nokia Corporation (qt-info@nokia.com)
|
|
|
|
##
|
|
|
|
## This file is part of the test suite of the Qt Toolkit.
|
|
|
|
##
|
|
|
|
## $QT_BEGIN_LICENSE:LGPL$
|
|
|
|
## GNU Lesser General Public License Usage
|
2011-05-24 09:34:08 +00:00
|
|
|
## This file may be used under the terms of the GNU Lesser General Public
|
|
|
|
## License version 2.1 as published by the Free Software Foundation and
|
|
|
|
## appearing in the file LICENSE.LGPL included in the packaging of this
|
|
|
|
## file. Please review the following information to ensure the GNU Lesser
|
|
|
|
## General Public License version 2.1 requirements will be met:
|
|
|
|
## http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
2011-04-27 10:05:43 +00:00
|
|
|
##
|
|
|
|
## In addition, as a special exception, Nokia gives you certain additional
|
2011-05-24 09:34:08 +00:00
|
|
|
## rights. These rights are described in the Nokia Qt LGPL Exception
|
2011-04-27 10:05:43 +00:00
|
|
|
## version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
|
|
|
##
|
2011-05-24 09:34:08 +00:00
|
|
|
## GNU General Public License Usage
|
|
|
|
## Alternatively, this file may be used under the terms of the GNU General
|
|
|
|
## Public License version 3.0 as published by the Free Software Foundation
|
|
|
|
## and appearing in the file LICENSE.GPL included in the packaging of this
|
|
|
|
## file. Please review the following information to ensure the GNU General
|
|
|
|
## Public License version 3.0 requirements will be met:
|
|
|
|
## http://www.gnu.org/copyleft/gpl.html.
|
|
|
|
##
|
|
|
|
## Other Usage
|
|
|
|
## Alternatively, this file may be used in accordance with the terms and
|
|
|
|
## conditions contained in a signed written agreement between you and Nokia.
|
2011-04-27 10:05:43 +00:00
|
|
|
##
|
|
|
|
##
|
|
|
|
##
|
|
|
|
##
|
|
|
|
##
|
|
|
|
## $QT_END_LICENSE$
|
|
|
|
##
|
|
|
|
#############################################################################
|
|
|
|
|
|
|
|
import sys
|
|
|
|
import os
|
|
|
|
import xml.dom.minidom
|
|
|
|
|
|
|
|
doc_cache = {}
|
|
|
|
|
|
|
|
class DraftResolution:
|
|
|
|
# See http://www.unicode.org/cldr/process.html for description
|
|
|
|
unconfirmed = 'unconfirmed'
|
|
|
|
provisional = 'provisional'
|
|
|
|
contributed = 'contributed'
|
|
|
|
approved = 'approved'
|
|
|
|
_values = { unconfirmed : 1, provisional : 2, contributed : 3, approved : 4 }
|
|
|
|
def __init__(self, resolution):
|
|
|
|
self.resolution = resolution
|
|
|
|
def toInt(self):
|
|
|
|
return DraftResolution._values[self.resolution]
|
|
|
|
|
|
|
|
class Error:
|
|
|
|
def __init__(self, msg):
|
|
|
|
self.msg = msg
|
|
|
|
def __str__(self):
|
|
|
|
return self.msg
|
|
|
|
|
|
|
|
def findChild(parent, tag_name, arg_name=None, arg_value=None, draft=None):
|
|
|
|
for node in parent.childNodes:
|
|
|
|
if node.nodeType != node.ELEMENT_NODE:
|
|
|
|
continue
|
|
|
|
if node.nodeName != tag_name:
|
|
|
|
continue
|
|
|
|
if arg_value:
|
|
|
|
if not node.attributes.has_key(arg_name):
|
|
|
|
continue
|
|
|
|
if node.attributes[arg_name].nodeValue != arg_value:
|
|
|
|
continue
|
|
|
|
if draft:
|
|
|
|
if not node.attributes.has_key('draft'):
|
|
|
|
# if draft is not specified then it's approved
|
|
|
|
return node
|
|
|
|
value = node.attributes['draft'].nodeValue
|
|
|
|
value = DraftResolution(value).toInt()
|
|
|
|
exemplar = DraftResolution(draft).toInt()
|
|
|
|
if exemplar > value:
|
|
|
|
continue
|
|
|
|
return node
|
|
|
|
return False
|
|
|
|
|
|
|
|
def findTagsInFile(file, path):
|
|
|
|
doc = False
|
|
|
|
if doc_cache.has_key(file):
|
|
|
|
doc = doc_cache[file]
|
|
|
|
else:
|
|
|
|
doc = xml.dom.minidom.parse(file)
|
|
|
|
doc_cache[file] = doc
|
|
|
|
|
|
|
|
elt = doc.documentElement
|
|
|
|
tag_spec_list = path.split("/")
|
|
|
|
last_entry = None
|
|
|
|
for i in range(len(tag_spec_list)):
|
|
|
|
tag_spec = tag_spec_list[i]
|
|
|
|
tag_name = tag_spec
|
|
|
|
arg_name = 'type'
|
|
|
|
arg_value = ''
|
|
|
|
left_bracket = tag_spec.find('[')
|
|
|
|
if left_bracket != -1:
|
|
|
|
tag_name = tag_spec[:left_bracket]
|
|
|
|
arg_value = tag_spec[left_bracket+1:-1].split("=")
|
|
|
|
if len(arg_value) == 2:
|
|
|
|
arg_name = arg_value[0]
|
|
|
|
arg_value = arg_value[1]
|
|
|
|
else:
|
|
|
|
arg_value = arg_value[0]
|
|
|
|
elt = findChild(elt, tag_name, arg_name, arg_value)
|
|
|
|
if not elt:
|
|
|
|
return None
|
|
|
|
ret = []
|
|
|
|
if elt.childNodes:
|
|
|
|
for node in elt.childNodes:
|
|
|
|
if node.attributes:
|
|
|
|
element = [node.nodeName, None]
|
|
|
|
element[1] = node.attributes.items()
|
|
|
|
ret.append(element)
|
|
|
|
else:
|
|
|
|
if elt.attributes:
|
|
|
|
element = [elt.nodeName, None]
|
|
|
|
element[1] = elt.attributes.items()
|
|
|
|
ret.append(element)
|
|
|
|
return ret
|
|
|
|
|
|
|
|
def _findEntryInFile(file, path, draft=None, attribute=None):
|
|
|
|
doc = False
|
|
|
|
if doc_cache.has_key(file):
|
|
|
|
doc = doc_cache[file]
|
|
|
|
else:
|
|
|
|
doc = xml.dom.minidom.parse(file)
|
|
|
|
doc_cache[file] = doc
|
|
|
|
|
|
|
|
elt = doc.documentElement
|
|
|
|
tag_spec_list = path.split("/")
|
|
|
|
last_entry = None
|
|
|
|
for i in range(len(tag_spec_list)):
|
|
|
|
tag_spec = tag_spec_list[i]
|
|
|
|
tag_name = tag_spec
|
|
|
|
arg_name = 'type'
|
|
|
|
arg_value = ''
|
|
|
|
left_bracket = tag_spec.find('[')
|
|
|
|
if left_bracket != -1:
|
|
|
|
tag_name = tag_spec[:left_bracket]
|
|
|
|
arg_value = tag_spec[left_bracket+1:-1].split("=")
|
|
|
|
if len(arg_value) == 2:
|
|
|
|
arg_name = arg_value[0]
|
|
|
|
arg_value = arg_value[1]
|
|
|
|
else:
|
|
|
|
arg_value = arg_value[0]
|
|
|
|
alias = findChild(elt, 'alias')
|
|
|
|
if alias and alias.attributes['source'].nodeValue == 'locale':
|
|
|
|
path = alias.attributes['path'].nodeValue
|
|
|
|
aliaspath = tag_spec_list[:i] + path.split("/")
|
|
|
|
def resolve(x, y):
|
|
|
|
if y == '..':
|
|
|
|
return x[:-1]
|
|
|
|
return x + [y]
|
|
|
|
# resolve all dot-dot parts of the path
|
|
|
|
aliaspath = reduce(resolve, aliaspath, [])
|
|
|
|
# remove attribute specification that our xpathlite doesnt support
|
|
|
|
aliaspath = map(lambda x: x.replace("@type=", "").replace("'", ""), aliaspath)
|
|
|
|
# append the remaining path
|
|
|
|
aliaspath = aliaspath + tag_spec_list[i:]
|
|
|
|
aliaspath = "/".join(aliaspath)
|
|
|
|
# "locale" aliases are special - we need to start lookup from scratch
|
|
|
|
return (None, aliaspath)
|
|
|
|
elt = findChild(elt, tag_name, arg_name, arg_value, draft)
|
|
|
|
if not elt:
|
|
|
|
return ("", None)
|
|
|
|
if attribute is not None:
|
|
|
|
if elt.attributes.has_key(attribute):
|
|
|
|
return (elt.attributes[attribute].nodeValue, None)
|
|
|
|
return (None, None)
|
|
|
|
return (elt.firstChild.nodeValue, None)
|
|
|
|
|
|
|
|
def findAlias(file):
|
|
|
|
if not doc_cache.has_key(file):
|
|
|
|
return False
|
|
|
|
doc = doc_cache[file]
|
|
|
|
alias_elt = findChild(doc.documentElement, "alias")
|
|
|
|
if not alias_elt:
|
|
|
|
return False
|
|
|
|
if not alias_elt.attributes.has_key('source'):
|
|
|
|
return False
|
|
|
|
return alias_elt.attributes['source'].nodeValue
|
|
|
|
|
|
|
|
def _findEntry(base, path, draft=None, attribute=None):
|
|
|
|
file = base
|
|
|
|
if base.endswith(".xml"):
|
|
|
|
filename = base
|
|
|
|
base = base[:-4]
|
|
|
|
else:
|
|
|
|
file = base + ".xml"
|
|
|
|
(dirname, filename) = os.path.split(base)
|
|
|
|
items = filename.split("_")
|
|
|
|
# split locale name into items and iterate through them from back to front
|
|
|
|
# example: az_Latn_AZ => [az_Latn_AZ, az_Latn, az]
|
|
|
|
items = reversed(map(lambda x: "_".join(items[:x+1]), range(len(items))))
|
|
|
|
for item in items:
|
|
|
|
file = dirname + "/" + item + ".xml"
|
|
|
|
if os.path.isfile(file):
|
|
|
|
alias = findAlias(file)
|
|
|
|
if alias:
|
|
|
|
# if alias is found we should follow it and stop processing current file
|
|
|
|
# see http://www.unicode.org/reports/tr35/#Common_Elements
|
|
|
|
aliasfile = os.path.dirname(file) + "/" + alias + ".xml"
|
|
|
|
if not os.path.isfile(aliasfile):
|
|
|
|
raise Error("findEntry: fatal error: found an alias '%s' to '%s', but the alias file couldnt be found" % (filename, alias))
|
|
|
|
# found an alias, recurse into parsing it
|
|
|
|
result = _findEntry(aliasfile, path, draft, attribute)
|
|
|
|
return result
|
|
|
|
(result, aliaspath) = _findEntryInFile(file, path, draft, attribute)
|
|
|
|
if aliaspath:
|
|
|
|
# start lookup again because of the alias source="locale"
|
|
|
|
return _findEntry(base, aliaspath, draft, attribute)
|
|
|
|
if result:
|
|
|
|
return result
|
|
|
|
return None
|
|
|
|
|
|
|
|
def findEntry(base, path, draft=None, attribute=None):
|
|
|
|
file = base
|
|
|
|
if base.endswith(".xml"):
|
|
|
|
file = base
|
|
|
|
base = base[:-4]
|
|
|
|
else:
|
|
|
|
file = base + ".xml"
|
|
|
|
(dirname, filename) = os.path.split(base)
|
|
|
|
|
|
|
|
result = None
|
|
|
|
while path:
|
|
|
|
result = _findEntry(base, path, draft, attribute)
|
|
|
|
if result:
|
|
|
|
return result
|
|
|
|
(result, aliaspath) = _findEntryInFile(dirname + "/root.xml", path, draft, attribute)
|
|
|
|
if result:
|
|
|
|
return result
|
|
|
|
if not aliaspath:
|
|
|
|
raise Error("findEntry: fatal error: %s: did not found key %s" % (filename, path))
|
|
|
|
path = aliaspath
|
|
|
|
|
|
|
|
return result
|
|
|
|
|