def __init__(self, name, params=None): self._name = name if params is None: self._params = OrderedDict() else: self._params = params self._sub_sections = OrderedDict()
class Arguments(object): """ Provides a wrapper around a list of :class:`Argument`. For example .. code-block:: python class PluginExample(Plugin): arguments = PluginArguments( PluginArgument("username", help="The username for your account.", metavar="EMAIL", requires=["password"]), // requires the password too PluginArgument("password", sensitive=True, // should be masked in logs, etc. help="The password for your account.", metavar="PASSWORD") ) This will add the ``--plugin-username`` and ``--plugin-password`` arguments to the CLI (assuming the plugin module is ``plugin``). """ def __init__(self, *args): self.arguments = OrderedDict((arg.name, arg) for arg in args) def __iter__(self): return iter(self.arguments.values()) def get(self, name): return self.arguments.get(name) def requires(self, name): """ Find all the arguments required by name :param name: name of the argument the find the dependencies :return: list of dependant arguments """ results = {name} argument = self.get(name) for reqname in argument.requires: required = self.get(reqname) if not required: raise KeyError( "{0} is not a valid argument for this plugin".format( reqname)) if required.name in results: raise RuntimeError("cycle detected in plugin argument config") results.add(required.name) yield required for r in self.requires(required.name): if r.name in results: raise RuntimeError( "cycle detected in plugin argument config") results.add(r.name) yield r
def load(self): import libxml2 d = libxml2.parseFile(self._file_name) root = d.getRootElement() params = root.xpathEval(XMLAdapter.XPATH_ALL_ATTRS) params_list = OrderedDict() for p in params: params_list[p.name] = p.content root_section = Section(root.name, params_list) # Recursively load all child nodes (and its params) # and interpret them as sections def load_sections(sec, root_node): for child_node in root_node.xpathEval(XMLAdapter.XPATH_ALL_CHILDS): params = child_node.xpathEval(XMLAdapter.XPATH_ALL_ATTRS) params_list = {} for p in params: params_list[p.name] = p.content chld_sec = sec.add_sub_section(Section(child_node.name, params_list)) load_sections(chld_sec, child_node) load_sections(root_section, root) d.freeDoc() return root_section
def read_xml(file, warnfunc=dummy_warn): """Load all resource names from an Android strings.xml resource file. The result is a dict of ``name => value``, `with ``value`` being either a string (a single string tag), a list (a string-array tag) or a dict (a plurals tag). """ result = OrderedDict() comment = [] try: doc = etree.parse(file) except etree.XMLSyntaxError, e: raise InvalidResourceError(e)
def get_keys(iterable): if not iterable: return [] return OrderedDict(iterable).keys()
def get_items(iterable): if not iterable: return [] return OrderedDict(iterable).items()
def __init__(self, language=None): OrderedDict.__init__(self) self.language = language
def __init__(self, *args): self.arguments = OrderedDict((arg.name, arg) for arg in args)
def po2xml(catalog, with_untranslated=False, filter=None, warnfunc=dummy_warn): """Convert the gettext catalog in ``catalog`` to an XML DOM. This currently relies entirely in the fact that we can use the context of each message to specify the Android resource name (which we need to do to handle duplicates, but this is a nice by-product). However that also means we cannot handle arbitrary catalogs. The latter would in theory be possible by using the original, untranslated XML to match up a messages id to a resource name, but right now we don't support this (and it's not clear it would be necessary, even). If ``with_untranslated`` is given, then strings in the catalog that have no translation are written out with the original id. In the case of a string-array, if ``with_untranslated`` is NOT specified, then only strings that DO have a translation are written out, potentially causing the array to be incomplete. TODO: This should not be the case: Arrays should always contain all elements, whether translated or not (using an empty string instead). When writing tests for this, make sure we generally test the with_untranslated mode, i.e. also the behavior for normal strings. """ # First, process the catalog into a Python sort-of-tree structure. # We can't write directly to the XML output, since stuff like # string-array items are not guaranteed to appear in the correct # order in the calalog. We "xml tree" pulls these things together. # It is quite similar to the structure returned by read_xml(). xml_tree = OrderedDict() for message in catalog: if not message.id: # This is the header continue if not message.string and not with_untranslated: # Untranslated. continue if not message.context: warnfunc(('Ignoring message "%s": has no context; somebody other '+ 'than android2po seems to have added to this '+ 'catalog.') % message.id, 'error') continue if filter and filter(message): continue value = message.string or message.id if ':' in message.context: # A colon indicates a string array; collect all the # strings of this array with their indices, so when # we're done processing the whole catalog, we can # sort by index and restore the proper array order. name, index = message.context.split(':', 2) xml_tree.setdefault(name, {}) if index in xml_tree[name]: warnfunc(('Duplicate index %s in array "%s"; ignoring '+ 'the message. The catalog has possibly been '+ 'corrupted.') % (index, name), 'error') xml_tree[name][index] = value else: xml_tree[message.context] = value # Convert the xml tree we've built into an actual Android XML DOM. root_tags = [] namespaces_used = {} for name, value in xml_tree.iteritems(): if isinstance(value, dict): # string-array - first, sort by index array_el = etree.Element('string-array') array_el.attrib['name'] = name for k in sorted(value, cmp=lambda x,y: cmp(int(x), int(y))): item_el = write_to_dom('item', value[k], message, namespaces_used, warnfunc) array_el.append(item_el) root_tags.append(array_el) else: # standard string string_el = write_to_dom('string', value, message, namespaces_used, warnfunc) string_el.attrib['name'] = name root_tags.append(string_el) # Generate the root element, define the namespaces that have been # used across all of our child elements. root_el = etree.Element('resources', nsmap=namespaces_used) for e in root_tags: root_el.append(e) return root_el
class Section(object): def __init__(self, name, params=None): self._name = name if params is None: self._params = OrderedDict() else: self._params = params self._sub_sections = OrderedDict() def __getitem__(self, index): return self.get_subsections_by_name(index) def __repr__(self): return 'Section %s (%s)' % (self.get_name(), self._params or '') def set_params(self, **params): self._params = params def get_params(self): return self._params def get_name(self): return self._name def add_sub_section(self, sec): key = sec.get_name() if key not in self._sub_sections: self._sub_sections[key] = [] self._sub_sections[key].append(sec) return sec def get_subsections_by_name(self, name): return self._sub_sections.get(name, []) def get_subsections_by_param_val(self, **kwargs): ret = [] for item in self.get_subsections(): item_match = True for k, v in kwargs.iteritems(): item_params = item.get_params() if k in item_params.keys(): if item_params[k] != v: item_match = False if item_match: ret.append(item) return ret def get_subsections(self): for subsec in self._sub_sections.itervalues(): for sub in subsec: yield sub def search_section_childs(self, section_name, param_name): return self._search_section_params(self, section_name, param_name) def _search_section_params(self, section, section_name, param_name): param_values = set() for s in section.get_subsections(): if s.get_name() == section_name: for key, val in s.get_params().iteritems(): if key == param_name: param_values.add(val) deeper_values = self._search_section_params(s, section_name, param_name) param_values |= deeper_values return param_values # Generator for subsections def __iter__(self): return self.get_subsections()
self._adapter.save(self._root_section) def load(self): self._root_section = self._adapter.load() if __name__ == '__main__': # Saving XML # Vytvoreni patricneho adapteru ad = XMLAdapter('file.xml') # Vytvoreni jakehosi "dokumentu" a jeho 'root' sekce doc = Document(ad) info_args = OrderedDict([("kernel", '3.10.0-244.el7.x86_64'), ("system_release", 'Red Hat Enterprise Linux Server release 7.1 (Maipo)'), ("hostname", 'ibm-x3650m3-02.lab.eng.brq.redhat.com') ]) r_section = Section('host', info_args) doc.create_root_section(r_section) doc.add_sub_section(Section("SanityTest")) subsecNetperf = doc.add_sub_section(Section("NetperfTCPStream")) # Vytvoreni dvou do sebe vnorenych podsekci subsection_1 = OrderedDict([("dstip", '172.18.10.20'), ("AF", 'INET4'), ("dstname", 'bnx2_1'), ("srcname", 'bnx2_1'), ("srcip", '172.18.10.10') ]) secPath = subsecNetperf.add_sub_section(Section('path', subsection_1))
def po2xml(catalog, with_untranslated=False, filter=None, warnfunc=dummy_warn): """Convert the gettext catalog in ``catalog`` to an XML DOM. This currently relies entirely in the fact that we can use the context of each message to specify the Android resource name (which we need to do to handle duplicates, but this is a nice by-product). However that also means we cannot handle arbitrary catalogs. The latter would in theory be possible by using the original, untranslated XML to match up a messages id to a resource name, but right now we don't support this (and it's not clear it would be necessary, even). If ``with_untranslated`` is given, then strings in the catalog that have no translation are written out with the original id. In the case of a string-array, if ``with_untranslated`` is NOT specified, then only strings that DO have a translation are written out, potentially causing the array to be incomplete. TODO: This should not be the case: Arrays should always contain all elements, whether translated or not (using an empty string instead). When writing tests for this, make sure we generally test the with_untranslated mode, i.e. also the behavior for normal strings. """ # First, process the catalog into a Python sort-of-tree structure. # We can't write directly to the XML output, since stuff like # string-array items are not guaranteed to appear in the correct # order in the calalog. We "xml tree" pulls these things together. # It is quite similar to the structure returned by read_xml(). xml_tree = OrderedDict() for message in catalog: if not message.id: # This is the header continue if not message.string and not with_untranslated: # Untranslated. continue if not message.context: warnfunc(('Ignoring message "%s": has no context; somebody other '+ 'than android2po seems to have added to this '+ 'catalog.') % message.id, 'error') continue if filter and filter(message): continue value = message.string or message.id if ':' in message.context: # A colon indicates a string array; collect all the # strings of this array with their indices, so when # we're done processing the whole catalog, we can # sort by index and restore the proper array order. name, index = message.context.split(':', 2) xml_tree.setdefault(name, {}) if index in xml_tree[name]: warnfunc(('Duplicate index %s in array "%s"; ignoring '+ 'the message. The catalog has possibly been '+ 'corrupted.') % (index, name), 'error') xml_tree[name][index] = value else: xml_tree[message.context] = value # Convert the xml tree we've built into an actual Android XML DOM. root_tags = [] namespaces_used = {} for name, value in xml_tree.iteritems(): if isinstance(value, dict): # string-array - first, sort by index array_el = etree.Element('string-array') array_el.attrib['name'] = name for k in sorted(value): item_el = write_to_dom('item', value[k], message, namespaces_used, warnfunc) array_el.append(item_el) root_tags.append(array_el) else: # standard string string_el = write_to_dom('string', value, message, namespaces_used, warnfunc) string_el.attrib['name'] = name root_tags.append(string_el) # Generate the root element, define the namespaces that have been # used across all of our child elements. root_el = etree.Element('resources', nsmap=namespaces_used) for e in root_tags: root_el.append(e) return root_el