50 # See http://www.unicode.org/cldr/process.html for description |
50 # See http://www.unicode.org/cldr/process.html for description |
51 unconfirmed = 'unconfirmed' |
51 unconfirmed = 'unconfirmed' |
52 provisional = 'provisional' |
52 provisional = 'provisional' |
53 contributed = 'contributed' |
53 contributed = 'contributed' |
54 approved = 'approved' |
54 approved = 'approved' |
55 |
55 _values = { unconfirmed : 1, provisional : 2, contributed : 3, approved : 4 } |
56 |
56 def __init__(self, resolution): |
57 def findChild(parent, tag_name, arg_value, draft=None): |
57 self.resolution = resolution |
|
58 def toInt(self): |
|
59 return DraftResolution._values[self.resolution] |
|
60 |
|
61 class Error: |
|
62 def __init__(self, msg): |
|
63 self.msg = msg |
|
64 def __str__(self): |
|
65 return self.msg |
|
66 |
|
67 def findChild(parent, tag_name, arg_name=None, arg_value=None, draft=None): |
58 for node in parent.childNodes: |
68 for node in parent.childNodes: |
59 if node.nodeType != node.ELEMENT_NODE: |
69 if node.nodeType != node.ELEMENT_NODE: |
60 continue |
70 continue |
61 if node.nodeName != tag_name: |
71 if node.nodeName != tag_name: |
62 continue |
72 continue |
63 if arg_value: |
73 if arg_value: |
64 if not node.attributes.has_key('type'): |
74 if not node.attributes.has_key(arg_name): |
65 continue |
75 continue |
66 if node.attributes['type'].nodeValue != arg_value: |
76 if node.attributes[arg_name].nodeValue != arg_value: |
67 continue |
77 continue |
68 if draft: |
78 if draft: |
69 if node.attributes.has_key('draft'): |
79 if not node.attributes.has_key('draft'): |
70 if node.attributes['draft'].nodeValue != draft: |
80 # if draft is not specified then it's approved |
71 continue |
81 return node |
72 elif draft != DraftResolution.approved: |
82 value = node.attributes['draft'].nodeValue |
|
83 value = DraftResolution(value).toInt() |
|
84 exemplar = DraftResolution(draft).toInt() |
|
85 if exemplar > value: |
73 continue |
86 continue |
74 return node |
87 return node |
75 return False |
88 return False |
76 |
89 |
77 def _findEntry(file, path, draft=None): |
90 def _findEntryInFile(file, path, draft=None, attribute=None): |
78 doc = False |
91 doc = False |
79 if doc_cache.has_key(file): |
92 if doc_cache.has_key(file): |
80 doc = doc_cache[file] |
93 doc = doc_cache[file] |
81 else: |
94 else: |
82 doc = xml.dom.minidom.parse(file) |
95 doc = xml.dom.minidom.parse(file) |
83 doc_cache[file] = doc |
96 doc_cache[file] = doc |
84 |
97 |
85 elt = doc.documentElement |
98 elt = doc.documentElement |
86 tag_spec_list = path.split("/") |
99 tag_spec_list = path.split("/") |
87 last_entry = None |
100 last_entry = None |
88 if draft is not None: |
101 for i in range(len(tag_spec_list)): |
89 last_entry = tag_spec_list[-1] |
102 tag_spec = tag_spec_list[i] |
90 tag_spec_list = tag_spec_list[:-1] |
|
91 for tag_spec in tag_spec_list: |
|
92 tag_name = tag_spec |
103 tag_name = tag_spec |
|
104 arg_name = 'type' |
93 arg_value = '' |
105 arg_value = '' |
94 left_bracket = tag_spec.find('[') |
106 left_bracket = tag_spec.find('[') |
95 if left_bracket != -1: |
107 if left_bracket != -1: |
96 tag_name = tag_spec[:left_bracket] |
108 tag_name = tag_spec[:left_bracket] |
97 arg_value = tag_spec[left_bracket+1:-1] |
109 arg_value = tag_spec[left_bracket+1:-1].split("=") |
98 elt = findChild(elt, tag_name, arg_value) |
110 if len(arg_value) == 2: |
|
111 arg_name = arg_value[0] |
|
112 arg_value = arg_value[1] |
|
113 else: |
|
114 arg_value = arg_value[0] |
|
115 alias = findChild(elt, 'alias') |
|
116 if alias and alias.attributes['source'].nodeValue == 'locale': |
|
117 path = alias.attributes['path'].nodeValue |
|
118 aliaspath = tag_spec_list[:i] + path.split("/") |
|
119 def resolve(x, y): |
|
120 if y == '..': |
|
121 return x[:-1] |
|
122 return x + [y] |
|
123 # resolve all dot-dot parts of the path |
|
124 aliaspath = reduce(resolve, aliaspath, []) |
|
125 # remove attribute specification that our xpathlite doesnt support |
|
126 aliaspath = map(lambda x: x.replace("@type=", "").replace("'", ""), aliaspath) |
|
127 # append the remaining path |
|
128 aliaspath = aliaspath + tag_spec_list[i:] |
|
129 aliaspath = "/".join(aliaspath) |
|
130 # "locale" aliases are special - we need to start lookup from scratch |
|
131 return (None, aliaspath) |
|
132 elt = findChild(elt, tag_name, arg_name, arg_value, draft) |
99 if not elt: |
133 if not elt: |
100 return "" |
134 return ("", None) |
101 if last_entry is not None: |
135 if attribute is not None: |
102 elt = findChild(elt, last_entry, '', draft) |
136 if elt.attributes.has_key(attribute): |
103 if not elt: |
137 return (elt.attributes[attribute].nodeValue, None) |
104 return "" |
138 return (None, None) |
105 return elt.firstChild.nodeValue |
139 return (elt.firstChild.nodeValue, None) |
106 |
140 |
107 def findAlias(file): |
141 def findAlias(file): |
|
142 if not doc_cache.has_key(file): |
|
143 return False |
108 doc = doc_cache[file] |
144 doc = doc_cache[file] |
109 alias_elt = findChild(doc.documentElement, "alias", "") |
145 alias_elt = findChild(doc.documentElement, "alias") |
110 if not alias_elt: |
146 if not alias_elt: |
111 return False |
147 return False |
112 if not alias_elt.attributes.has_key('source'): |
148 if not alias_elt.attributes.has_key('source'): |
113 return False |
149 return False |
114 return alias_elt.attributes['source'].nodeValue |
150 return alias_elt.attributes['source'].nodeValue |
115 |
151 |
116 def findEntry(base, path, draft=None): |
152 def _findEntry(base, path, draft=None, attribute=None): |
117 file = base + ".xml" |
153 file = base |
118 |
154 if base.endswith(".xml"): |
119 if os.path.isfile(file): |
155 filename = base |
120 result = _findEntry(file, path, draft) |
156 base = base[:-4] |
|
157 else: |
|
158 file = base + ".xml" |
|
159 (dirname, filename) = os.path.split(base) |
|
160 items = filename.split("_") |
|
161 # split locale name into items and iterate through them from back to front |
|
162 # example: az_Latn_AZ => [az_Latn_AZ, az_Latn, az] |
|
163 items = reversed(map(lambda x: "_".join(items[:x+1]), range(len(items)))) |
|
164 for item in items: |
|
165 file = dirname + "/" + item + ".xml" |
|
166 if os.path.isfile(file): |
|
167 alias = findAlias(file) |
|
168 if alias: |
|
169 # if alias is found we should follow it and stop processing current file |
|
170 # see http://www.unicode.org/reports/tr35/#Common_Elements |
|
171 aliasfile = os.path.dirname(file) + "/" + alias + ".xml" |
|
172 if not os.path.isfile(aliasfile): |
|
173 raise Error("findEntry: fatal error: found an alias '%s' to '%s', but the alias file couldnt be found" % (filename, alias)) |
|
174 # found an alias, recurse into parsing it |
|
175 result = _findEntry(aliasfile, path, draft, attribute) |
|
176 return result |
|
177 (result, aliaspath) = _findEntryInFile(file, path, draft, attribute) |
|
178 if aliaspath: |
|
179 # start lookup again because of the alias source="locale" |
|
180 return _findEntry(base, aliaspath, draft, attribute) |
|
181 if result: |
|
182 return result |
|
183 return None |
|
184 |
|
185 def findEntry(base, path, draft=None, attribute=None): |
|
186 file = base |
|
187 if base.endswith(".xml"): |
|
188 file = base |
|
189 base = base[:-4] |
|
190 else: |
|
191 file = base + ".xml" |
|
192 (dirname, filename) = os.path.split(base) |
|
193 |
|
194 result = None |
|
195 while path: |
|
196 result = _findEntry(base, path, draft, attribute) |
121 if result: |
197 if result: |
122 return result |
198 return result |
123 |
199 (result, aliaspath) = _findEntryInFile(dirname + "/root.xml", path, draft, attribute) |
124 alias = findAlias(file) |
|
125 if alias: |
|
126 file = os.path.dirname(base) + "/" + alias + ".xml" |
|
127 if os.path.isfile(file): |
|
128 result = _findEntry(file, path, draft) |
|
129 if result: |
|
130 return result |
|
131 |
|
132 file = base[:-3] + ".xml" |
|
133 if os.path.isfile(file): |
|
134 result = _findEntry(file, path, draft) |
|
135 if result: |
200 if result: |
136 return result |
201 return result |
137 alias = findAlias(file) |
202 if not aliaspath: |
138 if alias: |
203 raise Error("findEntry: fatal error: %s: did not found key %s" % (filename, path)) |
139 file = os.path.dirname(base) + "/" + alias + ".xml" |
204 path = aliaspath |
140 if os.path.isfile(file): |
205 |
141 result = _findEntry(file, path, draft) |
|
142 if result: |
|
143 return result |
|
144 |
|
145 if not draft: |
|
146 file = os.path.dirname(base) + "/root.xml" |
|
147 result = _findEntry(file, path, draft) |
|
148 return result |
206 return result |
149 |
207 |