def findUniqueChild(self, tag): """Returns the single child with the given nodeName. Raises Error if there is no such child or there is more than one.""" seq = self.findAllChildren(tag) try: node = seq.next() except StopIteration: raise Error('No child found where one was expected', tag) for it in seq: raise Error('Many children found where only one was expected', tag) return node
def __find(self, xpath): retries = [xpath.split('/')] while retries: tags, elts, roots = retries.pop(), self.nodes, (self.base.root, ) for selector in tags: tag, attrs = _parseXPath(selector) elts = tuple( _iterateEach(e.findAllChildren(tag, attrs) for e in elts)) if not elts: break else: # Found matching elements # Possibly filter elts to prefer the least drafty ? for elt in elts: yield elt # Process roots separately: otherwise the alias-processing # is excessive. for i, selector in enumerate(tags): tag, attrs = _parseXPath(selector) for alias in tuple( _iterateEach( r.findAllChildren('alias', allDull=True) for r in roots)): if alias.dom.attributes['source'].nodeValue == 'locale': replace = alias.dom.attributes['path'].nodeValue.split( '/') retries.append( self.__xpathJoin(tags[:i], replace, tags[i:])) roots = tuple( _iterateEach(r.findAllChildren(tag, attrs) for r in roots)) if not roots: if retries: # Let outer loop fall back on an alias path: break sought = '/'.join(tags) if sought != xpath: sought += f' (for {xpath})' raise Error( f'All lack child {selector} for {sought} in {self.name}' ) else: # Found matching elements for elt in roots: yield elt sought = '/'.join(tags) if sought != xpath: sought += f' (for {xpath})' raise Error(f'No {sought} in {self.name}')
def __enum(self, name, book, alias, suffix=None): assert book if suffix is None: suffix = name out, dupes = self.writer.write, self.__dupes out(' enum {} : ushort {{\n'.format(name)) for key, value in book.items(): member = value[0].replace('-', ' ') if name == 'Script': # Don't .capitalize() as some names are already camel-case (see enumdata.py): member = ''.join(word[0].upper() + word[1:] for word in member.split()) if not member.endswith('Script'): member += 'Script' if member in dupes: raise Error('The script name "{}" is messy'.format(member)) else: member = ''.join(member.split()) member = member + suffix if member in dupes else member out(' {} = {},\n'.format(member, key)) out('\n ' + ',\n '.join('{} = {}'.format(*pair) for pair in sorted(alias.items())) + ',\n\n Last{} = {}'.format(suffix, member)) # for "LastCountry = LastTerritory" # ### Qt 7: Remove if suffix != name: out(',\n Last{} = Last{}'.format(name, suffix)) out('\n };\n')
def tagCodes(self): """Yields four tag codes The tag codes are language, script, country and variant; an empty value for any of them indicates that no value was provided. The values are obtained from the primary file's top-level <identity> element. An Error is raised if any top-level <alias> element of this file has a non-empty source attribute; that attribute value is mentioned in the error's message.""" root = self.nodes[0] for alias in root.findAllChildren('alias', allDull=True): try: source = alias.dom.attributes['source'].nodeValue except (KeyError, AttributeError): pass else: raise Error('Alias to {}'.format(source)) ids = root.findUniqueChild('identity') for code in ('language', 'script', 'territory', 'variant'): for node in ids.findAllChildren(code, allDull=True): try: yield node.dom.attributes['type'].nodeValue except (KeyError, AttributeError): pass else: break # only want one value for each code else: # No value for this code, use empty yield ''
def __enum(self, name, book, alias, suffix=None): assert book if suffix is None: suffix = name out, dupes = self.writer.write, self.__dupes out(f' enum {name} : ushort {{\n') for key, value in book.items(): member = value[0].replace('-', ' ') if name == 'Script': # Don't .capitalize() as some names are already camel-case (see enumdata.py): member = ''.join(word[0].upper() + word[1:] for word in member.split()) if not member.endswith('Script'): member += 'Script' if member in dupes: raise Error(f'The script name "{member}" is messy') else: member = ''.join(member.split()) member = member + suffix if member in dupes else member out(f' {member} = {key},\n') out('\n ' + ',\n '.join(f'{k} = {v}' for k, v in sorted(alias.items())) + f',\n\n Last{suffix} = {member}') # for "LastCountry = LastTerritory" # ### Qt 7: Remove if suffix != name: out(f',\n Last{name} = Last{suffix}') out('\n };\n')
def __firstChildElt(cls, parent, name): child = parent.firstChild while child: if cls.__isNodeNamed(child, name): return child child = child.nextSibling raise Error('No {} child found'.format(name))
def append(self, s): if s in self.hash: return self.hash[s] lst = unicode2hex(s) index = len(self.data) if index > 0xffff: raise Error('Data index {} is too big for uint16!'.format(index)) size = len(lst) if size >= 0xffff: raise Error('Data is too big ({}) for uint16 size!'.format(size)) token = None try: token = StringDataToken(index, size) except Error as e: e.message += '(on data "{}")'.format(s) raise self.hash[s] = token self.data += lst return token
def append(self, s): s = s + '\0' if s in self.hash: return self.hash[s] lst = unicode2hex(s) index = len(self.data) if index > 0xffff: raise Error('Index ({}) outside the uint16 range !'.format(index)) self.hash[s] = index self.data += lst return index
def __enum(self, name, book, alias): assert book out, dupes = self.writer.write, self.__dupes out(' enum {} : ushort {{\n'.format(name)) for key, value in book.items(): member = value[0] if name == 'Script': # Don't .capitalize() as some names are already camel-case (see enumdata.py): member = ''.join(word[0].upper() + word[1:] for word in member.split()) if not member.endswith('Script'): member += 'Script' if member in dupes: raise Error('The script name "{}" is messy'.format(member)) else: member = ''.join(member.split()) member = member + name if member in dupes else member out(' {} = {},\n'.format(member, key)) out('\n ' + ',\n '.join('{} = {}'.format(*pair) for pair in sorted(alias.items())) + ',\n\n Last{} = {}\n }};\n'.format(name, member))
def __init__(self, index, length): if index > 0xFFFF or length > 0xFFFF: raise Error("Position exceeds ushort range: {},{}".format( index, length)) self.index = index self.length = length
def ordStr(c): if len(c) == 1: return str(ord(c)) raise Error('Unable to handle value "{}"'.format(addEscapes(c)))
def __complain(text): raise Error('Attempted to write data after closing :-(')